diff --git a/.gitignore b/.gitignore index 9f7006b05..48b02884c 100644 --- a/.gitignore +++ b/.gitignore @@ -44,30 +44,9 @@ target_wrapper.* # QtCtreator CMake CMakeLists.txt.user* -CMakeCache. -cmake_install.cmake -Makefile -__cmake_systeminformation *.pyc /build -/build* /icon/*.png /icon/ImageMagick - -# JetBrains IDE prefs -.idea/ - -# macOS annoyances -.DS_Store -*DS_Store -._* - -.cpm-cache/ - -# ninja -.ninja_deps -.ninja_lock -.ninja_log -build.ninja diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..e54b4f345 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,15 @@ +[submodule "src/singleapplication"] + path = src/singleapplication + url = https://github.com/itay-grudev/SingleApplication.git +[submodule "src/uchardet"] + path = src/uchardet + url = https://gitlab.freedesktop.org/uchardet/uchardet.git +[submodule "src/editorconfig-core-qt"] + path = src/editorconfig-core-qt + url = https://github.com/editorconfig/editorconfig-core-qt.git +[submodule "src/ads"] + path = src/ads + url = https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git +[submodule "src/QSimpleUpdater"] + path = src/QSimpleUpdater + url = https://github.com/alex-spataru/QSimpleUpdater diff --git a/README.md b/README.md index b972faf8f..13d97b74e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ There are numerous bugs and half working implementations. Pull requests are grea Packages are available for Windows, Linux, and MacOS. -Below are the supported distribution mechanisms. There may be other ways to download/install the application, but this project will likely not be able to offer any support for those since they are made available by other individuals. +Below are the supported distribution mechanisms. There may be other ways to download/install the application, but this project will likely not be able to offer any support for those since they are made availble by other individuals. ## Windows Windows packages are available as an installer or a stand-alone zip file on the [release](https://github.com/dail8859/NotepadNext/releases) page. The installer provides additional components such as an auto-updater and Windows context menu integration. You can easily install it with Winget: @@ -30,22 +30,13 @@ Linux packages can be obtained by downloading the stand-alone AppImage on the [r flatpak install flathub com.github.dail8859.NotepadNext ``` -If you are using Ubuntu and prefer an up-to-date deb version, you can use the [PPA supporting Ubuntu 22.04 and newer](https://launchpad.net/~quentiumyt/+archive/ubuntu/notepadnext) provided by -[Quentin Lienhardt](https://github.com/QuentiumYT). You can add it by executing: - -```bash -sudo add-apt-repository ppa:quentiumyt/notepadnext -sudo apt update -sudo apt install notepadnext -``` - ## MacOS MacOS disk images can be downloaded from the [release](https://github.com/dail8859/NotepadNext/releases) page. It can also be installed using brew: ```bash brew tap dail8859/notepadnext -brew install notepadnext +brew install --no-quarantine notepadnext ``` #### MacOS Tweaks @@ -59,9 +50,9 @@ defaults -currentHost write -g AppleFontSmoothing -int 0 A restart is required for this to take effect. # Development -Current development is done using QtCreator with the Microsoft Visual C++ (msvc) compiler. Qt 6.5 is the currently supported Qt version. Older versions of Qt are likely to work but are not tested. Any fixes for older versions will be accepted as long as they do not introduce complex fixes. This application is also known to build successfully on various Linux distributions and macOS. Other platforms/compilers should be usable with minor modifications. +Current development is done using QtCreator with the Microsft Visual C++ (msvc) compiler. Qt 6.5 is the prefered Qt version but this can also be built with Qt 5.15. This is also known to build successfully on various Linux distributions and macOS. Other platforms/compilers should be usable with minor modifications. -If you are familiar with building C++ Qt desktop applications with Qt Creator, then this should be as simple as opening `CMakeLists` and build/run the project. +If you are familiar with building C++ Qt desktop applications with Qt Creator, then this should be as simple as opening `src/NotepadNext.pro` and build/run the project. If you are new to building C++ Qt desktop applications, there is a more detailed guide [here](/doc/Building.md). diff --git a/deploy/linux/NotepadNext.desktop b/deploy/linux/NotepadNext.desktop index 62800d2eb..4e586d0f7 100644 --- a/deploy/linux/NotepadNext.desktop +++ b/deploy/linux/NotepadNext.desktop @@ -1,20 +1,10 @@ [Desktop Entry] -Categories=Qt;TextEditor;Utility; Exec=NotepadNext %f +Comment=A cross-platform, reimplementation of Notepad++ +Type=Application Icon=NotepadNext -MimeType=text/plain; +Name=Notepad Next StartupNotify=true -Type=Application Terminal=false - -Name=Notepad Next -Name[pt_BR]=Editor de Texto Notepad Next - -GenericName=Text Editor -GenericName[pt_BR]=Editor de Texto - -Comment=A cross-platform, reimplementation of Notepad++ -Comment[pt_BR]=O ‘Notepad Next’ é um editor de texto e editor de código-fonte, trata-se de uma reimplementação do Notepad++ para várias plataformas, possui compatibilidade para várias linguagens de programação e oferece traduções para vários idiomas - -Keywords=notepad;next;text;editor;manager;IDE;programming tool;source code;tabs; -Keywords[pt_BR]=notepad;next;bloco de notas;próximo;editor;texto;Ambiente de Desenvolvimento Integrado;IDE;ferramenta de programação;exibição de texto colorido;código-fonte;abas;guias; +Categories=Qt;TextEditor;Utility; +MimeType=text/plain; diff --git a/deploy/linux/com.github.dail8859.NotepadNext.metainfo.xml b/deploy/linux/com.github.dail8859.NotepadNext.metainfo.xml index 4e34eb8d7..3e7252098 100644 --- a/deploy/linux/com.github.dail8859.NotepadNext.metainfo.xml +++ b/deploy/linux/com.github.dail8859.NotepadNext.metainfo.xml @@ -26,12 +26,6 @@ com.github.dail8859.NotepadNext.desktop - - - - - - diff --git a/doc/Building.md b/doc/Building.md index e34b32a54..a93d81eed 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -1,10 +1,10 @@ # Building Notepad Next -To build Notepad Next you will need CMake, a compatible C++ compiler, the Qt libraries, and the Notepad Next source code. +To build Notepad Next you will need a compatible C++ compiler, the Qt libraries, and the Notepad Next source code. # Windows -This section specifically describes how to build Notepad Next using Microsoft's Visual Studio 2022 compiler. +This section specifically describes how to build Notepad Next using Microsoft's Visual Studio 2019 compiler. ## Installing Visual Studio 2022 @@ -18,7 +18,7 @@ This section specifically describes how to build Notepad Next using Microsoft's 1. Download the [Qt installer](https://www.qt.io/download-qt-installer) 1. Run the installer. 1. Select 'custom installation' -1. Install any version of Qt >= 6.5 (6.5 is recommended if possible) +1. Install any version of Qt >= 6.2 (5.15 may also work): * `MSVC 2019 64-bit` located under the desired version of Qt * `Qt 5 Compatibility Module` (not needed for Qt 5.x) * `Developer and Design Tools` > `Qt Creator CDB Debugger Support` @@ -27,55 +27,25 @@ This section specifically describes how to build Notepad Next using Microsoft's ## Cloning the Notepad Next Repository 1. In a command prompt (or git shell, powershell, etc) run: -1. `git clone https://github.com/dail8859/NotepadNext.git` +1. `git clone --recurse-submodules https://github.com/dail8859/NotepadNext.git` ## Building/Running Notepad Next -1. Open Qt Creator and open the root `CMakeLists.txt` file. -1. Configure the project for 'Desktop Qt 6.5 MSVC2019 64bit' (or whatever version of Qt you have installed) +1. Open `src/NotepadNext.pro` with Qt Creator +1. Configure the project for 'Desktop Qt 6.2.4 MSVC2019 64bit' 1. Press `Ctrl+R` 1. Qt Creator will build and run the project. # Linux -Here's instructions for ubuntu/debian. Should be same across all distros as long as you get the packages. -```sh -export DISTRIBUTION=AppImage -export EXTRA_PLATFORM_PLUGINS="libqwayland-generic.so" +Using a fresh Ubuntu 21.10 setup, the following script will install the needed dependencies and build the executable: -sudo apt update -sudo apt install -y \ - cmake \ - ninja-build \ - file \ - libxkbcommon-dev \ - libxkbcommon-x11-0 \ - fuse \ - libxcb-cursor-dev \ - libcups2-dev \ - libglib2.0-0 \ - libglib2.0-dev \ - libproxy1v5 \ - libproxy-dev \ - qt6-base-dev \ - qt6-base-dev-tools \ - qt6-tools-dev \ - qt6-tools-dev-tools \ - qt6-wayland \ - qt6-wayland-dev \ - libqt6waylandclient6 \ - qml6-module-qtwayland-compositor \ - libqt6core5compat6 \ - libqt6core5compat6-dev \ - qt6-base-private-dev - -cmake -S . -B build \ - -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ - -DAPP_DISTRIBUTION=$DISTRIBUTION -cmake --build build --target appimage --parallel ``` - -# MacOS - -TODO +sudo apt install qtbase5-dev qt5-qmake qtbase5-dev-tools qttools5-dev-tools qtbase5-private-dev libqt5x11extras5-dev build-essential git +git clone --recurse-submodules https://github.com/dail8859/NotepadNext.git +cd NotepadNext +mkdir build +cd build +qmake ../src/NotepadNext.pro +make -j$(nproc) +``` diff --git a/doc/Create Release.md b/doc/Create Release.md new file mode 100644 index 000000000..57696c4a4 --- /dev/null +++ b/doc/Create Release.md @@ -0,0 +1,29 @@ +## Prepare Release + +- Update version in `src/Version.pri` +- Add new `` tag to metainfo file in `deploy/linux` +- Commit +- Tag commit with new version number +- Push commit and tag to GitHub +- Once GitHub action finishes, edit draft notes of new release that was automatically created +- Publish + +## Manually Build Release +Example bat script to build release + +``` +call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64 +set PATH=C:\Qt\6.4.1\msvc2019_64\bin\;C:\Qt\Tools\QtCreator\bin\jom\;%PATH% +set PATH=C:\Program Files\7-Zip;%PATH% +set PATH=C:\Program Files (x86)\NSIS\Bin;%PATH% +mkdir build +cd build +qmake ..\src\NotepadNext.pro +jom +jom package +jom zip +jom installer +cd .. +copy build\NotepadNext*.zip . +copy installer\NotepadNext*.exe . +``` \ No newline at end of file diff --git a/doc/Translation.md b/doc/Translation.md new file mode 100644 index 000000000..36b1911b7 --- /dev/null +++ b/doc/Translation.md @@ -0,0 +1,43 @@ +# Translation + +## Overview of the Process + +1. Strings meant for translation are marked using `tr()` in the source code. +1. Qt's translation tool `lupdate` scans the source files for `tr()` and places the strings in a .ts XML file. At this point, the .ts file contains only strings that are meant to be translated. +1. A translator provides translations by opening the .ts file using Qt Linguist. At this point, the .ts file contains both the string to be translated and the translation. +1. When the application is built, the .ts files are converted into a binary .qm format. +1. The application loads the .qm files at runtime (depending on the locale/settings) and all `tr()` invocations are translated. + +## Required Tools + +For translators: +- Qt Linguist + +For developers: +- lupdate + +## Translation Process for Developers + +Follow the [Writing Source Code for Translation](https://doc.qt.io/qt-6/i18n-source-translation.html) guide to properly expose string to be translated. Once strings are ready to be released to translators, use the `lupdate` tool. If you use Qt creator, you can execute the lupdate command from the menu `Tools > External > Qt linguist > lupdate` or from the console/terminal: + +``` +$ lupdate NotepadNext.pro +``` + +When the application is built, it automatically uses `lrelease` to convert the list of .ts files into binary .qm files for the application to load. + +### Project Setup + +The included .ts files are listed `i18n.pri`. New locales names can be added to the `LOCALES` variable. + +## Translation Process for Translators + +If you want to help with translations but the target language is not supported yet, please open an issue and a new .ts file will be added you can use. If one already exists, open the appropriate .ts file with Qt Linguist and follow the [Qt Linguist Manual](https://doc.qt.io/qt-6/linguist-translators.html). Once changes have been made to the .ts file you can create a pull request so new translated strings can be included in the application. + +Qt Linguist is contained in the Qt SDK that you can download [here](https://www.qt.io/download-qt-installer). If you don't want to download the whole SDK, there is a community made a standalone version for Qt Linguist [here](https://github.com/lelegard/qtlinguist-installers/releases). + +## Reference and Detailed Info + +- [Internationalization with Qt](https://doc.qt.io/qt-6/internationalization.html) +- [Writing Source Code for Translation](https://doc.qt.io/qt-6/i18n-source-translation.html) +- [Qt Linguist Manual](https://doc.qt.io/qt-6/linguist-translators.html) diff --git a/doc/Update Scintilla.md b/doc/Update Scintilla.md index da4bab714..632007b01 100644 --- a/doc/Update Scintilla.md +++ b/doc/Update Scintilla.md @@ -1,4 +1,4 @@ -1. Delete all files in `thirdparty\scintilla` except `CMakeLists.txt` -1. Copy new release of Scintilla into `thirdparty\scintilla` -1. Change directory into `thirdparty\scintilla\qt\ScintillaEdit\` and run `python WidgetGen.py` -1. Update `thirdparty\scintilla\CMakeLists.txt` as needed \ No newline at end of file +1. Delete all files in `src\scintilla` +1. Copy new release of Scintilla into `src\scintilla` +1. Run `python src\scintilla\qt\ScintillaEdit\WidgetGen.py` +1. Update `src\scintilla.pri` as needed \ No newline at end of file diff --git a/i18n/NotepadNext_pl_PL.ts b/i18n/NotepadNext_pl_PL.ts new file mode 100644 index 000000000..ad811b693 --- /dev/null +++ b/i18n/NotepadNext_pl_PL.ts @@ -0,0 +1,2422 @@ + + + + + ColumnEditorDialog + + + Column Mode + Tryb kolumnowy + + + + Text + Tekst + + + + Numbers + Liczby + + + + Start: + Początek: + + + + Step: + Krok: + + + + DebugLogDock + + + Debug Log + Dziennik aplikacji + + + + Downloader + + + + Updater + Aktualizacje + + + + + + Downloading updates + Pobieranie aktualizacji + + + + Time remaining: 0 minutes + Pozostały czas: 0 minut + + + + Open + Otwórz + + + + + Stop + Zatrzymaj + + + + + Time remaining + Pozostały czas + + + + unknown + nieznany + + + + Error + Błąd + + + + Cannot find downloaded update! + Nie udało się znaleźć pobranej aktualizacji! + + + + Close + Zamknij + + + + Download complete! + Pobieranie zakończone! + + + + The installer will open separately + Instalator otworzy się w osobnym oknie + + + + Click "OK" to begin installing the update + Naciśnij "OK" aby zacząć instalację + + + + In order to install the update, you may need to quit the application. + Aby zainstalować aktualizację może być konieczne wyjście z aplikacji. + + + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + Aby zainstalować aktualizację może być konieczne wyjście z aplikacji. Ta aktualizacja jest obowiązkowa, wyjście spowoduje zamknięcie aplikacji + + + + Click the "Open" button to apply the update + Naciśnij klawisz "Otwórz" aby zastosować aktualizację + + + + Are you sure you want to cancel the download? + Czy na pewno chcesz anulować pobieranie? + + + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + Czy na pewno chcesz anulować pobieranie? Ta aktualizacja jest obowiązkowa, wyjście spowoduje zamknięcie aplikacji + + + + + %1 bytes + %1 bajtów + + + + + %1 KB + %1 KB + + + + + %1 MB + %1 MB + + + + of + z + + + + Downloading Updates + Pobieranie aktualizacji + + + + Time Remaining + Pozostały czas + + + + Unknown + nieznany + + + + about %1 hours + około %1 godzin + + + + about one hour + około godziny + + + + %1 minutes + %1 minut + + + + 1 minute + 1 minuta + + + + %1 seconds + %1 sekund + + + + 1 second + 1 sekunda + + + + EditorInfoStatusBar + + + Length: %L1 Lines: %L2 + Dług: %L1 Wierszy: %L2 + + + + Sel: N/A + Zazn: brak + + + + Sel: %L1 | %L2 + Zazn: %L1 | %L2 + + + + Ln: %L1 Col: %L2 + Wrs: %L1 Kol: %L2 + + + + Macintosh (CR) + Macintosh (CR) + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + ANSI + ANSI + + + + UTF-8 + UTF-8 + + + + EditorInspectorDock + + + Editor Inspector + Inspektor zaznaczenia + + + + Position Information + Informacja o pozycji + + + + Current Position + Bieżąca pozycja + + + + Current Position (x, y) + Bieżąca pozycja (x, y) + + + + Column + Kolumna + + + + Current Style + Bieżący styl + + + + Current Line + Bieżący wiersz + + + + Line Length + Długość wiersza + + + + Line End Position + Pozycja końca wiersza + + + + Line Indentation + Wcięcie wiersza + + + + Line Indent Position + Pozycja wcięcia wiersza + + + + Selection Information + Informacje o zaznaczeniu + + + + Mode + Tryb + + + + Is Rectangle + Czy prostokątne + + + + Selection Empty + Puste zaznaczenie + + + + Main Selection + Główne zaznaczenie + + + + # of Selections + Liczba zaznaczeń + + + + Multiple Selections + Wiele zaznaczeń + + + + Document Information + Informacja o dokumencie + + + + Length + Długość + + + + Line Count + Liczba wierszy + + + + View Information + Pokaż informacje + + + + Lines on Screen + Wierszy na ekranie + + + + First Visible Line + Pierwszy widoczny wiersz + + + + X Offset + Przesunięcie w poziomie + + + + Fold Information + Informacje o zwinięciu + + + + Visible From Doc Line + Widoczne od wiersza + + + + Doc Line From Visible + Wiersz od widocznego + + + + Fold Level + Poziom zagnieżdżenia + + + + Is Fold Header + Czy nagłówek zwinięcia + + + + Fold Parent + Rodzic zwinięcia + + + + Last Child + Ostatni potomek + + + + Contracted Fold Next + Następne zwinięcie + + + + Caret + Kursor + + + + Anchor + Kotwica + + + + Caret Virtual Space + Wirtualna przestrzeń kursora + + + + Anchor Virtual Space + Wirtualna przestrzeń kotwicy + + + + FileList + + + File List + Lista plików + + + + FindReplaceDialog + + + + + Find + Znajdź + + + + Search Mode + Tryb wyszukiwania + + + + &Normal + &Normalny + + + + E&xtended (\n, \r, \t, \0, \x...) + Rozsz&erzony (\n, \r, \t, \0, \x...) + + + + Re&gular expression + Wyrażenia re&gularne + + + + &. matches newline + &. nowy wiersz + + + + Transparenc&y + Przeźrocz&ystość + + + + On losing focus + Po utracie skupienia + + + + Always + Zawsze + + + + Coun&t + Policz + + + + &Replace + Zamień + + + + Replace &All + Zamień wszystko + + + + Replace All in &Opened Documents + Zamień wszystko w &otwartych plikach + + + + Find All in All &Opened Documents + Znajdź wszystko w &otwartych plikach + + + + Find All in Current Document + Znajdź wszystko w bieżącym pliku + + + + Close + Zamknij + + + + &Find: + Znajdź: + + + + Replace: + Zamień: + + + + Backward direction + Wstecz + + + + Match &whole word only + Całe sło&wa + + + + Match &case + Wielkość liter + + + + Wra&p Around + Zawijanie dokumentu + + + + Replace + Zamień + + + + + Replaced %Ln matches + + Zamieniono %Ln wystąpienie + Zamieniono %Ln wystąpienia + Zamieniono %Ln wystąpień + + + + + The end of the document has been reached. Found 1st occurrence from the top. + Osiągnięto koniec dokumentu. Znaleziono pierwsze wystąpienie od góry. + + + + No matches found. + Nie znaleziono żadnego wystąpienia. + + + + 1 occurrence was replaced + 1 wystąpienie zostało zamienione + + + + No more occurrences were found + Nie znaleziono więcej wystąpień + + + + Found %Ln matches + + Znaleziono %Ln wystąpienie + Znaleziono %Ln wystąpienia + Znaleziono %Ln wystąpień + + + + + FolderAsWorkspaceDock + + + Folder as Workspace + Folder jako obszar roboczy + + + + HexViewerDock + + + Hex Viewer + Podgląd heksadecymalny + + + + LanguageInspectorDock + + + Language Inspector + Inspektor języka + + + + Language: + Język: + + + + Lexer: + Lekser: + + + + Properties: + Właściwości: + + + + Property + Właściwość + + + + Type + Typ + + + + + Description + Opis + + + + Value + Wartość + + + + Keywords: + Słowa kluczowe: + + + + ID + ID + + + + Styles: + Style: + + + + TextLabel + TextLabel + + + + Position %1 Style %2 + Pozycja %1 Styl %2 + + + + LuaConsoleDock + + + Lua Console + Konsola Lua + + + + MacroEditorDialog + + + Macro Editor + Edytor makr + + + + Name + Nazwa + + + + Shortcut + Skrót + + + + Steps: + Działania: + + + + Insert Macro Step + Wstaw działanie + + + + Delete Selected Macro Step + Usuń wybrane działanie + + + + Move Selected Macro Step Up + Przesuń wybrane działanie w górę + + + + Move Selected Macro Step Down + Przesuń wybrane działanie w dół + + + + Copy Selected Macro + Skopiuj wybrane makro + + + + Delete Selected Macro + Usuń wybrane makro + + + + Delete Macro + Usuń makro + + + + Are you sure you want to delete <b>%1</b>? + Czy na pewno chcesz usunąć <b>%1</b>? + + + + (Copy) + (kopia) + + + + MacroRunDialog + + + Run a Macro Multiple Times + Wykonaj makro wiele razy + + + + Macro: + Makro: + + + + Run Until End of File + Wykonaj do końca pliku + + + + Execute... + Wykonaj... + + + + times + raz(y) + + + + Run + Uruchom + + + + Cancel + Anuluj + + + + MacroSaveDialog + + + Save Macro + Zapisz makro + + + + Name: + Nazwa: + + + + Shortcut: + Skrót: + + + + OK + OK + + + + Cancel + Anuluj + + + + MacroStepTableModel + + + Name + Nazwa + + + + Text + Tekst + + + + MainWindow + + + Notepad Next[*] + Notepad Next[*] + + + + + + + + + + + &File + Plik + + + + Close More + Zamknij więcej + + + + &Recent Files + Ostatnie pliki + + + + + Export As + Eksportuj jako + + + + &Edit + &Edycja + + + + Copy More + Kopiuj więcej + + + + Indent + Wcięcie + + + + EOL Conversion + Konwersja znaku końca wiersza + + + + Convert Case + Wielkość liter + + + + Line Operations + Operacje na wierszach + + + + Comment/Uncomment + Komentowanie/odkomentowanie + + + + Copy As + Kopiuj jako + + + + Encoding/Decoding + Kodowanie/dekodowanie + + + + Search + Szukaj + + + + Bookmarks + Zakładki + + + + &View + Widok + + + + &Zoom + Powięks&zenie + + + + Show Symbol + Pokaż symbole + + + + Fold Level + Poziom zagnieżdżenia + + + + Unfold Level + + + + + Language + Język + + + + Settings + Ustawienia + + + + Macro + Makra + + + + Help + Pomoc + + + + Encoding + Kodowanie + + + + Main Tool Bar + Główny pasek narzędziowy + + + + &New + &Nowy + + + + Create a new file + Utwórz nowy plik + + + + Ctrl+N + Ctrl+N + + + + &Open... + &Otwórz... + + + + Ctrl+O + Ctrl+O + + + + &Save + Zapi&sz + + + + Save + Zapisz + + + + Ctrl+S + Ctrl+S + + + + E&xit + Wyjdź + + + + &Undo + Cofnij + + + + Ctrl+Z + Ctrl+Z + + + + &Redo + Ponów + + + + Ctrl+Y + Ctrl+Y + + + + Cu&t + Wy&tnij + + + + Ctrl+X + Ctrl+X + + + + &Copy + Kopiuj + + + + Ctrl+C + Ctrl+C + + + + &Paste + Wklej + + + + Ctrl+V + Ctrl+V + + + + &Delete + Usuń + + + + Del + Del + + + + Copy Full Path + Kopiuj pełną ścieżkę + + + + Copy File Name + Kopiuj nazwę pliku + + + + Copy File Directory + Kopiuj folder pliku + + + + &Close + Zamknij + + + + Close the current file + Zamknij bieżący plik + + + + Ctrl+W + Ctrl+W + + + + Save &As... + Z&apisz jako... + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Save a Copy As... + Zapisz kopię jako... + + + + Sav&e All + Zapisz wszystko + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Select A&ll + Zaznacz wszystko + + + + Ctrl+A + Ctrl+A + + + + Increase Indent + Zwiększ wcięcie + + + + Decrease Indent + Zmniejsz wcięcie + + + + Rename... + Zmień nazwę... + + + + Re&load + Wczytaj ponownie + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + Macintosh (CR) + Macintosh (CR) + + + + UPPER CASE + WIELKIE LITERY + + + + Convert text to upper case + Konwersja do wielkich liter + + + + lower case + małe litery + + + + Convert text to lower case + Konwersja do małych liter + + + + Duplicate Current Line + Powiel bieżący wiersz + + + + Alt+Down + Alt+Down + + + + Split Lines + Podziel wiersze + + + + Join Lines + Połącz wiersze + + + + Ctrl+J + Ctrl+J + + + + Move Selected Lines Up + Przenieś zaznaczone wiersze w górę + + + + Ctrl+Shift+Up + Ctrl+Shift+Up + + + + Move Selected Lines Down + Przenieś zaznaczone wiersze w dół + + + + Ctrl+Shift+Down + Ctrl+Shift+Down + + + + Clos&e All + Zamknij wszystko + + + + Close All files + Zamknij wszystkie pliki + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Close All Except Active Document + Zamknij wszystko poza aktywnym dokumentem + + + + Close All to the Left + Zamknij wszystko po lewej + + + + Close All to the Right + Zamknij wszystko po prawej + + + + Zoom &In + Zw&iększ + + + + Ctrl++ + Ctrl++ + + + + Zoom &Out + Zmniejsz + + + + Ctrl+- + Ctrl+- + + + + Reset Zoom + Przywróć domyślne + + + + Ctrl+0 + Ctrl+0 + + + + About Qt + O Qt + + + + About Notepad Next + O Notepad Next + + + + Show Whitespace + Pokaż znaki niedrukowalne + + + + Show End of Line + Pokaż znaki końca wiersza + + + + Show All Characters + Pokaż wszystkie znaki + + + + Show Indent Guide + Pokaż linie wcięcia + + + + Show Wrap Symbol + Pokaż symbol zawijania + + + + Word Wrap + Zawijanie wierszy + + + + Restore Recently Closed File + Przywróć ostatnio zamknięty plik + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + Open All Recent Files + Otwórz wszystkie ostatnie pliki + + + + Clear Recent Files List + Wyczyść listę ostatnich plików + + + + &Find... + Znajdź... + + + + Ctrl+F + Ctrl+F + + + + Find in Files... + Znajdź w plikach... + + + + Find &Next + Znajdź &następne + + + + F3 + F3 + + + + Find &Previous + Znajdź &poprzednie + + + + &Replace... + Zamień + + + + Ctrl+H + Ctrl+H + + + + Full Screen + Pełny ekran + + + + F11 + F11 + + + + + Start Recording + Rozpocznij nagrywanie + + + + Playback + Odtwórz + + + + Ctrl+Shift+P + Ctrl+Shift+P + + + + Save Current Recorded Macro... + Zapisz bieżące makro... + + + + Run a Macro Multiple Times... + Uruchom makro wiele razy... + + + + Preferences... + Preferencje... + + + + Quick Find + Szybkie wyszukiwanie + + + + Ctrl+Alt+I + Ctrl+Alt+I + + + + Select Next Instance + Zaznacz następne wystąpienie + + + + Ctrl+D + Ctrl+D + + + + Move to Trash... + Przenieś do kosza... + + + + Move to Trash + Przenieś do kosza + + + + Check for Updates... + Sprawdź aktualizacje... + + + + &Go to Line... + Idź do wiersza... + + + + Ctrl+G + Ctrl+G + + + + Print... + Drukuj... + + + + Ctrl+P + Ctrl+P + + + + Open Folder as Workspace... + Otwórz folder jako obszar roboczy... + + + + Toggle Single Line Comment + Przełącz komentarz pojedynczego wiersza + + + + Ctrl+/ + Ctrl+/ + + + + Single Line Comment + Zakomentuj wiersz + + + + Ctrl+K + Ctrl+K + + + + Single Line Uncomment + Odkomentuj wiersz + + + + Ctrl+Shift+K + Ctrl+Shift+K + + + + Edit Macros... + Edytor makr... + + + + This is not currently implemented + Ta funkcja nie jest obecnie zaimplementowana + + + + Column Mode... + Tryb kolumnowy... + + + + Export as HTML... + Eksportuj jako HTML... + + + + Export as RTF... + Eksportuj jako RTF... + + + + Copy as HTML + Kopiuj jako HTML + + + + Copy as RTF + Kopiuj jako RTF + + + + Base 64 Encode + Kodowanie Base 64 + + + + URL Encode + Kodowanie URL + + + + Base 64 Decode + Dekodowanie Base 64 + + + + URL Decode + Dekodowanie URL + + + + Copy URL + Kopiuj URL + + + + Remove Empty Lines + Usuń puste wiersze + + + + + Show in Explorer + Pokaż w eksploratorze + + + + Open Command Prompt Here + Otwórz wiersz poleceń + + + + Toggle Bookmark + Przełącz zakładki + + + + Ctrl+F2 + Ctrl+F2 + + + + Next Bookmark + Następna zakładka + + + + F2 + F2 + + + + Previous Bookmark + Poprzednia zakładka + + + + Shift+F2 + Shift+F2 + + + + Clear Bookmarks + Wyczyść zakładki + + + + Invert Bookmarks + Odwróć zakładki + + + + Next Tab + + + + + Ctrl+Tab + + + + + Previous Tab + + + + + Ctrl+Shift+Tab + + + + + Fold Level 1 + + + + + Alt+1 + + + + + Fold Level 2 + + + + + Alt+2 + + + + + Fold Level 3 + + + + + Alt+3 + + + + + Fold Level 4 + + + + + Alt+4 + + + + + Unfold Level 1 + + + + + Alt+Shift+1 + + + + + Unfold Level 2 + + + + + Alt+Shift+2 + + + + + Unfold Level 3 + + + + + Alt+Shift+3 + + + + + Unfold Level 4 + + + + + Alt+Shift+4 + + + + + Fold All + + + + + Alt+0 + + + + + Unfold All + + + + + Alt+Shift+0 + + + + + Fold Level 5 + + + + + Alt+5 + + + + + Fold Level 6 + + + + + Alt+6 + + + + + Fold Level 7 + + + + + Alt+7 + + + + + Fold Level 8 + + + + + Alt+8 + + + + + Fold Level 9 + + + + + Alt+9 + + + + + Unfold Level 5 + + + + + Alt+Shift+5 + + + + + Unfold Level 6 + + + + + Alt+Shift+6 + + + + + Unfold Level 7 + + + + + Alt+Shift+7 + + + + + Unfold Level 8 + + + + + Alt+Shift+8 + + + + + Unfold Level 9 + + + + + Alt+Shift+9 + + + + + Go to line + Idź do wiersza + + + + Line Number (1 - %1) + Numer wiersza (1-%1) + + + + Stop Recording + Zakończ nagrywanie + + + + New %1 + Nowy %1 + + + + Create File + Utwórz plik + + + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> nie istnieje. Czy chcesz go utworzyć? + <b>%1</b> nie istnieje. Czy chcesz go utworzyć? + + + + + Save file <b>%1</b>? + Zapisać plik <b>%1</b>? + + + + + Save File + Zapisz plik + + + + Open Folder as Workspace + Otwórz folder jako obszar roboczy + + + + Reload File + Wczytaj plik ponownie + + + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + Czy na pewno chcesz ponownie wczytać<b>%1</b>? Niezapisane zmiany zostaną utracone. + + + + Save a Copy As + Zapisz kopię jako + + + + + Rename + Zmień nazwę + + + + Name: + Nazwa: + + + + Delete File + Usuń plik + + + + Are you sure you want to move <b>%1</b> to the trash? + Czy na pewno chcesz przenieść <b>%1</b> do kosza? + + + + Error Deleting File + Błąd podczas usuwania pliku + + + + Something went wrong deleting <b>%1</b>? + Coś poszło nie tak przy próbie usunięcia <b>%1</b>? + + + + Administrator + Administrator + + + + Error Saving File + Błąd podczas zapisywania pliku + + + + An error occurred when saving <b>%1</b><br><br>Error: %2 + Pojawił się błąd podczas próby zapisania <b>%1</b><br><br>Błąd: %2 + + + + Zoom: %1% + Powiększenie: %1% + + + + No updates are available at this time. + Brak dostępnych aktualizacji. + + + + PreferencesDialog + + + Preferences + Preferencje + + + + Show menu bar + Pokaż pasek menu + + + + Show toolbar + Pokaż pasek narzędzi + + + + Show status bar + Pokaż pasek stanu + + + + Restore previous session + Przywróć poprzednią sesję + + + + Unsaved changes + Niezapisane zmiany + + + + Temporary files + Pliki tymczasowe + + + + Combine search results + Połącz wyniki wyszukiwania + + + + Translation: + Język interfejsu: + + + + Exit on last tab closed + + + + + Default Font + + + + + Font + + + + + Font Size + + + + + pt + + + + + TextLabel + TextLabel + + + + An application restart is required to apply certain settings. + Wymagany jest restart aplikacji aby zastosować te ustawienia. + + + + Warning + Uwaga + + + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + Ta funkcja jest eksperymentalna i nie powinna być używana w ważnych zastosowaniach. Jej użycie może prowadzić do utraty danych. Używaj jej na własną odpowiedzialność. + + + + <System Default> + <domyślny systemowy> + + + + QObject + + + List All Tabs + Lista wszystkich kart + + + + Detach Group + Odłącz grupę + + + + Minimize + Minimalizuj + + + + Close Tab + Zamknij kartę + + + + QuickFindWidget + + + Frame + Ramka + + + + Match case + Dopasuj wielkość liter + + + + Aa + Aa + + + + Match whole word + Dopasuj całe słowa + + + + |A| + |A| + + + + Use regular expression + Użyj wyrażenia regularnego + + + + . * + . * + + + + Alt+E + Alt+E + + + + Find... + Znajdź... + + + + %L1/%L2 + + + + + SearchResultsDock + + + Search Results + Wyniki wyszukiwania + + + + Collapse All + Zwiń wszystko + + + + Expand All + Rozwiń wszystko + + + + Delete Entry + Usuń wpis + + + + Delete All + Usuń wszystko + + + + Updater + + + Would you like to download the update now? + Czy chcesz teraz pobrać aktualizację? + + + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + Czy chcesz teraz pobrać aktualizację? Ta aktualizacja jest obowiązkowa, wyjście spowoduje zamknięcie aplikacji + + + + Version %1 of %2 has been released! + Wersja %1 %2 jest dostępna! + + + + No updates are available for the moment + Brak dostępnych aktualizacji + + + + Congratulations! You are running the latest version of %1 + Gratulacje! Masz najnowszą wersję %1 + + + + ads::CAutoHideTab + + + Detach + Odłącz + + + + Pin To... + Przypnij do... + + + + Top + Góra + + + + Left + Lewo + + + + Right + Prawo + + + + Bottom + Dół + + + + Unpin (Dock) + Odepnij (dokowanie) + + + + Close + Zamknij + + + + ads::CDockAreaTitleBar + + + Detach + Odłącz + + + + Detach Group + Odłącz grupę + + + + + Unpin (Dock) + Odepnij (dokowanie) + + + + + Pin Group + Przypnij grupę + + + + Pin Group To... + Przypnij grupę do... + + + + Top + Góra + + + + Left + Lewo + + + + Right + Prawo + + + + Bottom + Dół + + + + + Minimize + Minimalizuj + + + + + + Close + Zamknij + + + + + Close Group + Zamknij grupę + + + + Close Other Groups + Zamknij inne grupy + + + + Pin Active Tab (Press Ctrl to Pin Group) + Przypnij aktywną kartę (naciśnij Ctrl aby przypiąć grupę) + + + + Close Active Tab + Zamknij aktywną kartę + + + + ads::CDockManager + + + Show View + Pokaż widok + + + + ads::CDockWidgetTab + + + Detach + Odłącz + + + + Pin + Przypnij + + + + Pin To... + Przypnij do... + + + + Top + Góra + + + + Left + Lewo + + + + Right + Prawo + + + + Bottom + Dół + + + + Close + Zamknij + + + + Close Others + Zamknij inne + + + diff --git a/i18n/NotepadNext_pt_PT.ts b/i18n/NotepadNext_pt_PT.ts index 6e7368c99..2c82287c3 100644 --- a/i18n/NotepadNext_pt_PT.ts +++ b/i18n/NotepadNext_pt_PT.ts @@ -1,2327 +1,2421 @@ - - + + ColumnEditorDialog - - Column Mode - Modo de coluna + + Column Mode + Modo de coluna - - Text - Texto + + Text + Texto - - Numbers - Números + + Numbers + Números - - Start: - Iniciar: + + Start: + Iniciar: - - Step: - Etapa: + + Step: + Etapa: - - + + DebugLogDock - - Debug Log - Registo de depuração + + Debug Log + Registo de depuração - - - EditorInfoStatusBar + + + Downloader - - Length: %L1 Lines: %L2 - Comprimento: %L1 Linhas: %L2 + + + Updater + Atualizador - - Sel: N/A - Sel: N/D + + + + Downloading updates + Transferir atualizações - - Sel: %L1 | %L2 - Sel: %L1 | %L2 + + Time remaining: 0 minutes + Tempo restante: 0 minutos - - Ln: %L1 Col: %L2 - Ln: %L1 Col: %L2 + + Open + Abrir - - Macintosh (CR) - Macintosh (CR) + + + Stop + Parar - - Windows (CR LF) - Windows (CR LF) + + + Time remaining + Tempo restante - - Unix (LF) - Unix (LF) + + unknown + desconhecido - - ANSI - ANSI + + Error + Erro - - UTF-8 - UTF-8 + + Cannot find downloaded update! + Não é possível encontrar a atualização transferida! - - UTF-8 BOM - + + Close + Fechar - - UTF-16LE BOM - + + Download complete! + Transferência concluída! - - UTF-16BE BOM - + + The installer will open separately + O instalador será aberto separadamente - - OVR - This is a short abbreviation to indicate characters will be replaced when typing - SUB + + Click "OK" to begin installing the update + Clique em “OK” para começar a instalar a atualização - - INS - This is a short abbreviation to indicate characters will be inserted when typing - INS + + In order to install the update, you may need to quit the application. + Para instalar a atualização, poderá ser necessário sair da aplicação. - - - EditorInspectorDock - - Editor Inspector - Inpetor de editor + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + Para instalar a atualização, poderá ser necessário sair da aplicação. Esta é uma atualização obrigatória, sair agora fechará a aplicação - - Position Information - Informação da posição + + Click the "Open" button to apply the update + Clique no botão “Abrir” para aplicar a atualização - - Current Position - Posição atual + + Are you sure you want to cancel the download? + Tem a certeza de que pretende cancelar a transferência? - - Current Position (x, y) - Posição atual (x, y) + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + Tem a certeza de que pretende cancelar a transferência? Esta é uma atualização obrigatória, sair agora irá fechar a aplicação - - Column - Coluna + + + %1 bytes + %1 bytes - - Current Style - Estilo atual + + + %1 KB + %1 KB - - Current Line - Linha atual + + + %1 MB + %1 MB - - Line Length - Comprimento da linha + + of + de - - Line End Position - Posição final da linha + + Downloading Updates + Transferir Atualizações - - Line Indentation - Indentação de linha + + Time Remaining + Tempo Restante - - Line Indent Position - Posição de indentação de linha + + Unknown + Desconhecido - - Selection Information - Informação de seleção + + about %1 hours + cerca de %1 horas - - Mode - Modo + + about one hour + cerca de 1 hora - - Is Rectangle - É retângulo + + %1 minutes + %1 minutos - - Selection Empty - Seleção vazia + + 1 minute + 1 minuto - - Main Selection - Seleção principal + + %1 seconds + %1 segundos - - # of Selections - # de seleções + + 1 second + 1 segundo + + + EditorInfoStatusBar - - Multiple Selections - Seleções múltiplas + + Length: %L1 Lines: %L2 + Comprimento: %L1 Linhas: %L2 - - Document Information - Informação sobre o documento + + Sel: N/A + Sel: N/D - - Length - Comprimento + + Sel: %L1 | %L2 + Sel: %L1 | %L2 - - Line Count - Contagem de linhas + + Ln: %L1 Col: %L2 + Ln: %L1 Col: %L2 - - View Information - Ver informação + + Macintosh (CR) + Macintosh (CR) - - Lines on Screen - Linhas no ecrã + + Windows (CR LF) + Windows (CR LF) - - First Visible Line - Primeira linha visível + + Unix (LF) + Unix (LF) - - X Offset - Desvio X + + ANSI + ANSI - - Fold Information - Informações sobre a dobra + + UTF-8 + UTF-8 + + + EditorInspectorDock - - Visible From Doc Line - Visível a partir da linha Doc + + Editor Inspector + Inpetor de editor - - Doc Line From Visible - Linha Doc a partir de Visível + + Position Information + Informação da posição - - Fold Level - Nível de dobra + + Current Position + Posição atual - - Is Fold Header - É cabeçalho de dobra + + Current Position (x, y) + Posição atual (x, y) - - Fold Parent - Dobrar acima + + Column + Coluna - - Last Child - Último abaixo + + Current Style + Estilo atual - - Contracted Fold Next - Dobra contratada Seguinte + + Current Line + Linha atual - - Caret - Carácter + + Line Length + Comprimento da linha - - Anchor - Ancoragem + + Line End Position + Posição final da linha - - Caret Virtual Space - Espaço virtual do carácter + + Line Indentation + Indentação de linha - - Anchor Virtual Space - Espaço virtual da ancoragem + + Line Indent Position + - - - FileList - - File List - Lista de ficheiros + + Selection Information + Informação de seleção - - ... - ... + + Mode + Modo - - Sort by File Name - Ordenar por nome de ficheiro + + Is Rectangle + É retângulo - - - FindReplaceDialog - - - - Find - Localizar + + Selection Empty + Seleção vazia - - Search Mode - Modo de pesquisa + + Main Selection + Seleção principal - - &Normal - &Normal + + # of Selections + # de seleções - - E&xtended (\n, \r, \t, \0, \x...) - A&largada (\n, \r, \t, \0, \x...) + + Multiple Selections + Seleções múltiplas - - Re&gular expression - Expressão re&gular + + Document Information + Informação sobre o documento - - &. matches newline - &. corresponde a uma nova linha + + Length + Comprimento - - Transparenc&y - Transparênc&ia + + Line Count + Contagem de linhas - - On losing focus - Sobre perder o foco + + View Information + Ver informação - - Always - Sempre + + Lines on Screen + Linhas no ecrã - - Coun&t - Con&tar + + First Visible Line + Primeira linha visível - - &Replace - &Substituir + + X Offset + Desvio X - - Replace &All - Substituir &tudo + + Fold Information + Informações sobre a dobra - - Replace All in &Opened Documents - Substituir tudo em documentos &abertos + + Visible From Doc Line + Visível a partir da linha Doc - - Find All in All &Opened Documents - Localizar tudo em todos os documentos &abertos + + Doc Line From Visible + Linha Doc a partir de Visível - - Find All in Current Document - Localizar tudo no documento atual + + Fold Level + Nível de dobra - - Close - Fechar + + Is Fold Header + É cabeçalho de dobra - - &Find: - &Localizar: + + Fold Parent + Dobrar acima - - Replace: - Substituir: + + Last Child + Último abaixo - - Backward direction - Sentido inverso + + Contracted Fold Next + Dobra contratada Seguinte - - Match &whole word only - Corresponder apenas à palavra &inteira + + Caret + Carácter - - Match &case - Corresponder &minúsculas/maiúsculas + + Anchor + Ancoragem - - Wra&p Around - En&volvente + + Caret Virtual Space + Espaço virtual do carácter - - Replace - Substituir + + Anchor Virtual Space + Espaço virtual da ancoragem - - - - Replaced %Ln matches - - Substituído %Ln correspondência - Substituído %Ln correspondências - + + + FileList + + + File List + Lista de ficheiros + + + FindReplaceDialog - - The end of the document has been reached. Found 1st occurrence from the top. - O fim do documento foi atingido. Localizada a 1ª ocorrência a partir do topo. + + + + Find + Localizar - - No matches found. - Não foram localizadas correspondências. + + Search Mode + Modo de pesquisa - - 1 occurrence was replaced - 1 ocorrência foi substituída + + &Normal + &Normal - - No more occurrences were found - + + E&xtended (\n, \r, \t, \0, \x...) + A&largada (\n, \r, \t, \0, \x...) - - - Found %Ln matches - - Localizado %Ln correspondência - Localizado %Ln correspondências - - - - - FolderAsWorkspaceDock - - Folder as Workspace - Pasta como área de trabalho + + Re&gular expression + Expressão re&gular - - - LanguageInspectorDock - - Language Inspector - Inspetor de linguagem + + &. matches newline + &. corresponde a uma nova linha - - Language: - Linguagem: + + Transparenc&y + Transparênc&ia - - Lexer: - Lexer: + + On losing focus + Sobre perder o foco - - Properties: - Propriedades: + + Always + Sempre - - Property - Propriedade + + Coun&t + Con&tar - - Type - Tipo + + &Replace + &Substituir - - - Description - Descrição + + Replace &All + Substituir &tudo - - Value - Valor + + Replace All in &Opened Documents + Substituir tudo em documentos &abertos - - Keywords: - Palavras-chave: + + Find All in All &Opened Documents + Localizar tudo em todos os documentos &abertos - - ID - ID + + Find All in Current Document + Localizar tudo no documento atual - - Styles: - Estilos: + + Close + Fechar - - TextLabel - Legenda do texto + + &Find: + &Localizar: - - Position %1 Style %2 - Posição %1 Estilo %2 + + Replace: + Substituir: - - - LuaConsoleDock - - Lua Console - Consola Lua + + Backward direction + Sentido inverso - - - MacroEditorDialog - - Macro Editor - Editor de macros + + Match &whole word only + Corresponder apenas à palavra &inteira - - Name - Nome + + Match &case + Corresponder &minúsculas/maiúsculas - - Shortcut - Atalho + + Wra&p Around + En&volvente - - Steps: - Etapas: + + Replace + Substituir + + + + + Replaced %Ln matches + + Substituído %Ln correspondência + Substituído %Ln correspondências + - - Insert Macro Step - Inserir etapa da macro + + The end of the document has been reached. Found 1st occurrence from the top. + O fim do documento foi atingido. Localizada a 1ª ocorrência a partir do topo. - - Delete Selected Macro Step - Eliminar a etapa da macro selecionada + + No matches found. + Não foram localizadas correspondências. - - Move Selected Macro Step Up - Mover a etapa da macro selecionada para cima + + 1 occurrence was replaced + 1 ocorrência foi substituída - - Move Selected Macro Step Down - Mover a etapa da macro selecionada para baixo + + No more occurrences were found + + + + Found %Ln matches + + Localizado %Ln correspondência + Localizado %Ln correspondências + + + + + FolderAsWorkspaceDock - - Copy Selected Macro - Copiar a macro selecionada + + Folder as Workspace + Pasta como área de trabalho + + + HexViewerDock - - Delete Selected Macro - Eliminar a macro selecionada + + Hex Viewer + Visualizador Hexadecimal + + + LanguageInspectorDock - - Delete Macro - Eliminar macro + + Language Inspector + Inspetor de linguagem - - Are you sure you want to delete <b>%1</b>? - Tem a certeza de que pretende eliminar <b>%1</b>? + + Language: + Linguagem: - - (Copy) - (Copiar) + + Lexer: + Lexer: - - - MacroRunDialog - - Run a Macro Multiple Times - Executar uma macro várias vezes + + Properties: + Propriedades: - - Macro: - Macro: + + Property + Propriedade - - Run Until End of File - Executar até ao fim do ficheiro + + Type + Tipo - - Execute... - Executar... + + + Description + Descrição - - times - vezes + + Value + Valor - - Run - Executar + + Keywords: + Palavras-chave: - - Cancel - Cancelar + + ID + ID - - - MacroSaveDialog - - Save Macro - Guardar macro + + Styles: + Estilos: - - Name: - Nome: + + TextLabel + Legenda do texto - - Shortcut: - Atalho: + + Position %1 Style %2 + Posição %1 Estilo %2 + + + LuaConsoleDock - - OK - OK + + Lua Console + Consola Lua + + + MacroEditorDialog - - Cancel - Cancelar + + Macro Editor + Editor de macros - - - MacroStepTableModel - - Name - Nome + + Name + Nome - - Text - Texto + + Shortcut + Atalho + + + + Steps: + Etapas: + + + + Insert Macro Step + Inserir etapa da macro - - - MainWindow - - Notepad Next[*] - Notepad Next[*] + + Delete Selected Macro Step + Eliminar a etapa da macro selecionada - - + - + + + Move Selected Macro Step Up + Mover a etapa da macro selecionada para cima - - &File - &Ficheiro + + Move Selected Macro Step Down + Mover a etapa da macro selecionada para baixo - - Close More - Fechar mais + + Copy Selected Macro + Copiar a macro selecionada - - &Recent Files - Ficheiros &recentes + + Delete Selected Macro + Eliminar a macro selecionada - - - Export As - Exportar como + + Delete Macro + Eliminar macro - - &Edit - &Editar + + Are you sure you want to delete <b>%1</b>? + Tem a certeza de que pretende eliminar <b>%1</b>? - - Copy More - Copiar mais + + (Copy) + (Copiar) + + + MacroRunDialog - - Indent - Indentação + + Run a Macro Multiple Times + Executar uma macro várias vezes - - EOL Conversion - Conversão de fim de linha + + Macro: + Macro: - - Convert Case - Converter maiúsculas/minúsculas + + Run Until End of File + Executar até ao fim do ficheiro - - Line Operations - Operações de linha + + Execute... + Executar... - - Comment/Uncomment - Comentar/Não comentar + + times + vezes - - Copy As - Copiar como + + Run + Executar - - Encoding/Decoding - Codificação/Decodificação + + Cancel + Cancelar + + + MacroSaveDialog - - Search - Procurar + + Save Macro + Guardar macro - - Bookmarks - Marcadores + + Name: + Nome: - - Mark All Occurrences - Selecionar todas as ocorrências + + Shortcut: + Atalho: - - Clear Marks - Remover as seleções + + OK + OK - - &View - &Ver + + Cancel + Cancelar + + + MacroStepTableModel - - &Zoom - &Zoom + + Name + Nome - - Show Symbol - Mostrar símbolo + + Text + Texto + + + MainWindow - - Fold Level - Nível de dobra + + Notepad Next[*] + Notepad Next[*] - - Unfold Level - Nível de desdobra + + + + + - - Language - Linguagem + + &File + &Ficheiro - - Settings - Definições + + Close More + Fechar mais - - Macro - Macro + + &Recent Files + Ficheiros &recentes - - Help - Ajuda + + + Export As + Exportar como - - Encoding - Codificação + + &Edit + &Editar - - Main Tool Bar - Barra de ferramentas principal + + Copy More + Copiar mais - - &New - &Novo + + Indent + - - Create a new file - Criar um novo ficheiro + + EOL Conversion + Conversão de Fim De Linha - - Ctrl+N - Ctrl+N + + Convert Case + Converter maiúsculas/minúsculas - - &Open... - &Abrir... + + Line Operations + Operações de linha - - Ctrl+O - Ctrl+O + + Comment/Uncomment + Comentar/Não comentar - - &Save - &Guardar + + Copy As + Copiar como - - Save - Guardar + + Encoding/Decoding + Codificação/Decodificação - - Ctrl+S - Ctrl+S + + Search + Procurar - - E&xit - Sa&ir + + Bookmarks + Marcadores - - &Undo - An&ular + + &View + &Ver - - Ctrl+Z - Ctrl+Z + + &Zoom + &Zoom - - &Redo - &Refazer + + Show Symbol + Mostrar símbolo - - Ctrl+Y - Ctrl+Y + + Fold Level + Nível de dobra - - Cu&t - Cor&tar + + Unfold Level + Nível de desdobra - - Ctrl+X - Ctrl+X + + Language + Linguagem - - &Copy - &Copiar + + Settings + Definições - - Ctrl+C - Ctrl+C + + Macro + Macro - - &Paste - &Colar + + Help + Ajuda - - Ctrl+V - Ctrl+V + + Encoding + Codificação - - &Delete - &Eliminar + + Main Tool Bar + Barra de ferramentas principal - - Del - Ctrl+V + + &New + &Novo - - Copy Full Path - Copiar localização completa + + Create a new file + Criar um novo ficheiro - - Copy File Name - Copiar nome de ficheiro + + Ctrl+N + Ctrl+N - - Copy File Directory - Copiar diretório de ficheiros + + &Open... + &Abrir... - - &Close - &Fechar + + Ctrl+O + Ctrl+O - - Close the current file - Fechar o ficheiro atual + + &Save + &Guardar - - Ctrl+W - Ctrl+W + + Save + Guardar - - Save &As... - Guardar &como... + + Ctrl+S + Ctrl+S - - Ctrl+Alt+S - Ctrl+Alt+S + + E&xit + Sa&ir - - Save a Copy As... - Guardar uma cópia como... + + &Undo + An&ular - - Sav&e All - Guar&dar tudo + + Ctrl+Z + Ctrl+Z - - Ctrl+Shift+S - Ctrl+Shift+S + + &Redo + &Refazer - - Select A&ll - Selecionar t&udo + + Ctrl+Y + Ctrl+Y - - Ctrl+A - Ctrl+A + + Cu&t + Cor&tar - - Increase Indent - Aumentar a indentação + + Ctrl+X + Ctrl+X - - Decrease Indent - Diminuir a indentação + + &Copy + &Copiar - - Rename... - Renomear... + + Ctrl+C + Ctrl+C - - Re&load - Re&carregar + + &Paste + &Colar - - Windows (CR LF) - Windows (CR LF) + + Ctrl+V + Ctrl+V - - Unix (LF) - Unix (LF) + + &Delete + &Eliminar - - Macintosh (CR) - Macintosh (CR) + + Del + Ctrl+V - - UPPER CASE - MAIÚSCULAS + + Copy Full Path + Copiar localização completa - - Convert text to upper case - Converter texto em maiúsculas + + Copy File Name + Copiar nome de ficheiro - - lower case - minúsculas + + Copy File Directory + Copiar diretório de ficheiros - - Convert text to lower case - Converter texto em minúsculas + + &Close + &Fechar - - Duplicate Current Line - Duplicar linha atual + + Close the current file + Fechar o ficheiro atual - - Alt+Down - Alt+Baixo + + Ctrl+W + Ctrl+W - - Split Lines - Dividir linhas + + Save &As... + Guardar &como... - - Join Lines - Juntar linhas + + Ctrl+Alt+S + Ctrl+Alt+S - - Ctrl+J - Ctrl+J + + Save a Copy As... + Guardar uma cópia como... - - Move Selected Lines Up - Mover as linhas selecionadas para cima + + Sav&e All + Guar&dar tudo - - Ctrl+Shift+Up - Ctrl+Shift+Cima + + Ctrl+Shift+S + Ctrl+Shift+S - - Move Selected Lines Down - Mover as linhas selecionadas para baixo + + Select A&ll + Selecionar t&udo - - Ctrl+Shift+Down - Ctrl+Shift+Baixo + + Ctrl+A + Ctrl+A - - Clos&e All - Fechar &tudo + + Increase Indent + Aumentar o recuo - - Close All files - Fechar todos os ficheiros + + Decrease Indent + Diminuir o recuo - - Ctrl+Shift+W - Ctrl+Shift+W + + Rename... + Renomear... - - Close All Except Active Document - Fechar tudo exceto o documento ativo + + Re&load + Re&carregar - - Close All to the Left - Fechar tudo à esquerda + + Windows (CR LF) + Windows (CR LF) - - Close All to the Right - Fechar tudo à direita + + Unix (LF) + Unix (LF) - - Zoom &In - A&umentar + + Macintosh (CR) + Macintosh (CR) - - Ctrl++ - Ctrl++ + + UPPER CASE + MAIÚSCULAS - - Zoom &Out - &Reduzir + + Convert text to upper case + Converter texto em maiúsculas - - Ctrl+- - Ctrl+- + + lower case + minúsculas - - Reset Zoom - Repor + + Convert text to lower case + Converter texto em minúsculas - - Ctrl+0 - Ctrl+0 + + Duplicate Current Line + Duplicar linha atual - - About Qt - Acerca do Qt + + Alt+Down + Alt+Baixo - - About Notepad Next - Acerca do Notepad Next + + Split Lines + Dividir linhas - - Show Whitespace - Mostrar espaço em branco + + Join Lines + Juntar linhas - - Show End of Line - Mostrar fim de linha + + Ctrl+J + Ctrl+J - - Show All Characters - Mostrar todos os caracteres + + Move Selected Lines Up + Mover as linhas selecionadas para cima - - Show Indent Guide - Mostrar guia de indentação + + Ctrl+Shift+Up + Ctrl+Shift+Cima - - Show Wrap Symbol - Mostrar o símbolo de quebra de linha + + Move Selected Lines Down + Mover as linhas selecionadas para baixo - - Word Wrap - Quebra de palavras + + Ctrl+Shift+Down + Ctrl+Shift+Baixo - - Restore Recently Closed File - Restaurar ficheiro fechado recentemente + + Clos&e All + Fechar &tudo - - Ctrl+Shift+T - Ctrl+Shift+T + + Close All files + Fechar todos os ficheiros - - Open All Recent Files - Abrir todos os ficheiros recentes + + Ctrl+Shift+W + Ctrl+Shift+W - - Clear Recent Files List - Limpar a lista dos ficheiros recentes + + Close All Except Active Document + Fechar tudo exceto o documento ativo - - &Find... - &Localizar... + + Close All to the Left + Fechar tudo à esquerda - - Ctrl+F - Ctrl+F + + Close All to the Right + Fechar tudo à direita - - Find in Files... - Localizar em Ficheiros... + + Zoom &In + A&umentar - - Find &Next - Localizar &seguinte + + Ctrl++ + Ctrl++ - - F3 - F3 + + Zoom &Out + &Reduzir - - Find &Previous - Localizar &anterior + + Ctrl+- + Ctrl+- - - Shift+F3 - + + Reset Zoom + Repor - - &Replace... - &Substituir... + + Ctrl+0 + Ctrl+0 - - Ctrl+H - Ctrl+H + + About Qt + Acerca do Qt - - Full Screen - Ecrã inteiro + + About Notepad Next + Acerca do Notepad Next - - F11 - F11 + + Show Whitespace + Mostrar espaço em branco - - - Start Recording - Iniciar gravação + + Show End of Line + Mostrar fim de linha - - Playback - Reproduzir + + Show All Characters + Mostrar todos os caracteres - - Ctrl+Shift+P - Ctrl+Shift+P + + Show Indent Guide + Mostrar guia de indentação - - Save Current Recorded Macro... - Guardar a macro gravada atual... + + Show Wrap Symbol + Mostrar o símbolo de quebra de linha - - Run a Macro Multiple Times... - Executar uma macro várias vezes... + + Word Wrap + Quebra de palavras - - Preferences... - Preferências... + + Restore Recently Closed File + Restaurar ficheiro fechado recentemente - - Quick Find - Pesquisa rápida + + Ctrl+Shift+T + Ctrl+Shift+T - - Ctrl+Alt+I - Ctrl+Alt+I + + Open All Recent Files + Abrir todos os ficheiros recentes - - Select Next Instance - Selecionar a instância seguinte + + Clear Recent Files List + Limpar a lista de ficheiros recentes - - Ctrl+D - Ctrl+D + + &Find... + &Localizar... - - Move to Trash... - Mover para o Lixo... + + Ctrl+F + Ctrl+F - - Move to Trash - Mover para o Lixo + + Find in Files... + localizar em Ficheiros... - - Check for Updates... - Procurar por atualizações... + + Find &Next + Localizar &seguinte - - &Go to Line... - &Ir para a linha... + + F3 + F3 - - Ctrl+G - Ctrl+G + + Find &Previous + Localiza &anterior - - Print... - Imprimir... + + &Replace... + &Substituir... - - Ctrl+P - Ctrl+P + + Ctrl+H + Ctrl+H - - Open Folder as Workspace... - Abrir pasta como área de trabalho... + + Full Screen + Ecrã inteiro - - Toggle Single Line Comment - Alternar comentário de linha única + + F11 + F11 - - Ctrl+/ - Ctrl+/ + + + Start Recording + Iniciar gravação - - Single Line Comment - Comentário de linha única + + Playback + Reproduzir - - Ctrl+K - Ctrl+K + + Ctrl+Shift+P + Ctrl+Shift+P - - Single Line Uncomment - Sem comentário de linha única + + Save Current Recorded Macro... + Guardar a macro gravada atual... - - Ctrl+Shift+K - Ctrl+Shift+K + + Run a Macro Multiple Times... + Executar uma macro várias vezes... - - Edit Macros... - Editar macros... + + Preferences... + Preferências... - - This is not currently implemented - Atualmente não está implementado + + Quick Find + Pesquisa rápida - - Column Mode... - Modo de coluna... + + Ctrl+Alt+I + Ctrl+Alt+I - - Export as HTML... - Exportar como HTML... + + Select Next Instance + Selecionar a instância seguinte - - Export as RTF... - Exportar como RTF... + + Ctrl+D + Ctrl+D - - Copy as HTML - Copiar como HTML + + Move to Trash... + Mover para o Lixo... - - Copy as RTF - Copiar como RTF + + Move to Trash + Mover para o Lixo - - Base 64 Encode - Codificação Base 64 + + Check for Updates... + Procurar por atualizações... - - URL Encode - Codificação URL + + &Go to Line... + &Ir para a linha... - - Base 64 Decode - Descodificação Base 64 + + Ctrl+G + Ctrl+G - - URL Decode - Descodificação URL + + Print... + Imprimir... - - Copy URL - Copiar URL + + Ctrl+P + Ctrl+P - - Remove Empty Lines - Remover linhas vazias + + Open Folder as Workspace... + Abrir pasta como área de trabalho... - - - Show in Explorer - Mostrar no Explorador + + Toggle Single Line Comment + Alternar comentário de linha única - - Open %1 Here - Abrir %1 aqui + + Ctrl+/ + Ctrl+/ - - Toggle Bookmark - Alternar marcador + + Single Line Comment + Comentário de linha única - - Ctrl+F2 - Ctrl+F2 + + Ctrl+K + Ctrl+K - - Next Bookmark - Marcador seguinte + + Single Line Uncomment + Sem comentário de linha única - - F2 - F2 + + Ctrl+Shift+K + Ctrl+Shift+K - - Previous Bookmark - Marcador anterior + + Edit Macros... + Editar macros... - - Shift+F2 - Shift+F2 + + This is not currently implemented + Atualmente não está implementado - - Clear Bookmarks - Limpar marcadores + + Column Mode... + Modo de coluna... - - Invert Bookmarks - Inverter marcadores + + Export as HTML... + Exportar como HTML... - - Next Tab - Separarador seguinte + + Export as RTF... + Exportar como RTF... - - Ctrl+Tab - Ctrl+Tab + + Copy as HTML + Copiar como HTML - - Previous Tab - Separador anterior + + Copy as RTF + Copiar como RTF - - Ctrl+Shift+Tab - Ctrl+Shift+Tab + + Base 64 Encode + Codificação Base 64 - - Fold Level 1 - Nível de dobra 1 + + URL Encode + Codificação URL - - Alt+1 - Alt+1 + + Base 64 Decode + Descodificação Base 64 - - Fold Level 2 - Nível de dobra 2 + + URL Decode + Descodificação URL - - Alt+2 - Alt+2 + + Copy URL + Copiar URL - - Fold Level 3 - Nível de dobra 3 + + Remove Empty Lines + Remover linhas vazias - - Alt+3 - Alt+3 + + + Show in Explorer + Mostrar no Explorador - - Fold Level 4 - Nível de dobra 4 + + Open Command Prompt Here + Abrir a janela de comandos aqui - - Alt+4 - Alt+4 + + Toggle Bookmark + Alternar marcador - - Unfold Level 1 - Nível de desdobra 1 + + Ctrl+F2 + Ctrl+F2 - - Alt+Shift+1 - Alt+Shift+1 + + Next Bookmark + Marcador seguinte - - Unfold Level 2 - Nível de desdobra 2 + + F2 + F2 - - Alt+Shift+2 - Alt+Shift+2 + + Previous Bookmark + Marcador anterior - - Unfold Level 3 - Nível de desdobra 3 + + Shift+F2 + Shift+F2 - - Alt+Shift+3 - Alt+Shift+3 + + Clear Bookmarks + Limpar marcadores - - Unfold Level 4 - Nível de desdobra 4 + + Invert Bookmarks + Inverter marcadores - - Alt+Shift+4 - Alt+Shift+4 + + Next Tab + Separarador seguinte - - Fold All - Dobrar tudo + + Ctrl+Tab + Ctrl+Tab - - Alt+0 - Alt+0 + + Previous Tab + Separador anterior - - Unfold All - Desdobrar tudo + + Ctrl+Shift+Tab + Ctrl+Shift+Tab - - Alt+Shift+0 - Alt+Shift+0 + + Fold Level 1 + Nível de dobra 1 - - Fold Level 5 - Nível de dobra 5 + + Alt+1 + Alt+1 - - Alt+5 - Alt+5 + + Fold Level 2 + Nível de dobra 2 - - Fold Level 6 - Nível de dobra 6 + + Alt+2 + Alt+2 - - Alt+6 - Alt+6 + + Fold Level 3 + Nível de dobra 3 - - Fold Level 7 - Nível de dobra 7 + + Alt+3 + Alt+3 - - Alt+7 - Alt+7 + + Fold Level 4 + Nível de dobra 4 - - Fold Level 8 - Nível de dobra 8 + + Alt+4 + Alt+4 + Alt+4 - - Alt+8 - Alt+8 + + Unfold Level 1 + Nível de desdobra 1 - - Fold Level 9 - Nível de dobra 9 + + Alt+Shift+1 + Alt+Shift+1 - - Alt+9 - Alt+9 + + Unfold Level 2 + Nível de desdobra 2 - - Unfold Level 5 - Nível de desdobra 5 + + Alt+Shift+2 + Alt+Shift+2 - - Alt+Shift+5 - Alt+Shift+5 + + Unfold Level 3 + Nível de desdobra 3 - - Unfold Level 6 - Nível de desdobra 6 + + Alt+Shift+3 + Alt+Shift+3 - - Alt+Shift+6 - Alt+Shift+6 + + Unfold Level 4 + Nível de desdobra 4 - - Unfold Level 7 - Nível de desdobra 7 + + Alt+Shift+4 + Alt+Shift+4 - - Alt+Shift+7 - Alt+Shift+7 + + Fold All + Dobrar tudo - - Unfold Level 8 - Nível de desdobra 8 + + Alt+0 + Alt+0 + Alt+0 - - Alt+Shift+8 - Alt+Shift+8 + + Unfold All + Desdobrar tudo - - Unfold Level 9 - Nível de desdobra 9 + + Alt+Shift+0 + Alt+Shift+0 - - Alt+Shift+9 - Alt+Shift+9 + + Fold Level 5 + Nível de dobra 5 - - - Toggle Overtype - Alternar entre tipos + + Alt+5 + Alt+5 - - Ins - Ins + + Fold Level 6 + Nível de dobra 6 - - Debug Info... - Informações de depuração... + + Alt+6 + Alt+6 - - Cut Bookmarked Lines - Cortar linhas com marcadores + + Fold Level 7 + Nível de dobra 7 - - Copy Bookmarked Lines - Copiar linhas com marcadores + + Alt+7 + Alt+7 - - Delete Bookmarked Lines - Eliminar linhas com marcadores + + Fold Level 8 + Nível de dobra 8 - - Mark Style 1 - Estilo da seleção 1 + + Alt+8 + Alt+8 - - Mark Style 2 - Estilo da seleção 2 + + Fold Level 9 + Nível de dobra 9 - - Clear Style 1 - Remover o estilo 1 + + Alt+9 + Alt+9 - - Clear Style 2 - Remover o estilo 2 + + Unfold Level 5 + Nível de desdobra 5 - - Mark Style 3 - Estilo da seleção 3 + + Alt+Shift+5 + Alt+Shift+5 - - Clear Style 3 - Remover o estilo 3 + + Unfold Level 6 + Nível de desdobra 6 - - - Clear All Styles - Remover todos os estilos + + Alt+Shift+6 + Alt+Shift+6 - - Remove Duplicate Lines - + + Unfold Level 7 + Nível de desdobra 7 - - Remove Consecutive Duplicate Lines - + + Alt+Shift+7 + Alt+Shift+7 - - Sort Lines Ascending - + + Unfold Level 8 + Nível de desdobra 8 - - Sort Lines Descending - + + Alt+Shift+8 + Alt+Shift+8 - - Sort Lines Ascending (Case-Insensitive) - + + Unfold Level 9 + Nível de desdobra 9 - - Sort Lines Descending (Case-Insensitive) - + + Alt+Shift+9 + Alt+Shift+9 - - Sort Lines by Length Ascending - + + Go to line + Ir para a linha - - Sort Lines by Length Descending - + + Line Number (1 - %1) + Número da linha (1 - %1) - - Reverse Line Order - + + Stop Recording + Parar gravação - - Go to line - Ir para a linha + + New %1 + Novo %1 - - Line Number (1 - %1) - Número da linha (1 - %1) + + Create File + Criar ficheiro - - Stop Recording - Parar gravação + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> não existe. Pretende criá-lo? - - Debug Info - Informações de depuração + + + Save file <b>%1</b>? + Guardar ficheiro <b>%1</b>? - - New %1 - Novo %1 + + + Save File + Guardar ficheiro - - Create File - Criar ficheiro + + Open Folder as Workspace + Abrir pasta como área de trabalho - - <b>%1</b> does not exist. Do you want to create it? - <b>%1</b> não existe. Pretende criá-lo? + + Reload File + Recarregar ficheiro - - - Save file <b>%1</b>? - Guardar ficheiro <b>%1</b>? + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + Tem certeza de que pretende recarregar o <b>%1</b>? Todas as alterações não guardadas serão perdidas. - - - Save File - Guardar ficheiro + + Save a Copy As + Guardar uma cópia como - - Open Folder as Workspace - Abrir pasta como área de trabalho + + + Rename + Renomear - - - Reload File - Recarregar ficheiro + + Name: + Nome: - - Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. - Tem certeza de que pretende recarregar o <b>%1</b>? Todas as alterações não guardadas serão perdidas. + + Delete File + Eliminar ficheiro - - Save a Copy As - Guardar uma cópia como + + Are you sure you want to move <b>%1</b> to the trash? + Tem a certeza de que pretende mover <b>%1</b> para o lixo? - - - Rename - Renomear + + Error Deleting File + Erro ao eliminar ficheiro - - Name: - Nome: + + Something went wrong deleting <b>%1</b>? + Algo correu mal ao eliminar <b>%1</b>? - - Delete File - Eliminar ficheiro + + Administrator + Administrador - - Are you sure you want to move <b>%1</b> to the trash? - Tem a certeza de que pretende mover <b>%1</b> para o lixo? + + Error Saving File + Erro ao guardar ficheiro - - Error Deleting File - Erro ao eliminar ficheiro + + An error occurred when saving <b>%1</b><br><br>Error: %2 + Ocorreu um erro ao guardar <b>%1</b><br><br>Erro: %2 - - Something went wrong deleting <b>%1</b>? - Algo correu mal ao eliminar <b>%1</b>? + + Zoom: %1% + Zoom: %1% - - Administrator - Administrador + + No updates are available at this time. + De momento, não há atualizações disponíveis. + + + PreferencesDialog - - <b>%1</b> has been modified by another program. Do you want to reload it? - <b>%1</b> foi modificado por outro programa. Deseja recarregá-lo? + + Preferences + Preferências - - Read error - + + Show menu bar + Mostrar barra de menus - - Write error - + + Show toolbar + Mostrar barra de ferramentas - - Fatal error - + + Show status bar + Mostrar barra de estado - - Resource error - + + Restore previous session + Restaurar a sessão anterior - - Open error - + + Unsaved changes + Alterações não guardadas - - Abort error - + + Temporary files + Ficheiros temporários - - Timeout error - + + Combine search results + Combinar resultados de pesquisa - - Unspecified error - + + Translation: + Tradução: - - Remove error - + + Exit on last tab closed + Sair no último separador fechado - - Rename error - + + Default Font + Tipo de letra predefinida - - Position error - + + Font + Tipo de letra - - Resize error - + + Font Size + Tamanho do tipo de letra - - Permissions error - + + pt + pt - - Copy error - + + TextLabel + Legenda - - Unknown error (%1) - + + An application restart is required to apply certain settings. + É necessário reiniciar a aplicação para aplicar determinadas definições. - - Error Saving File - Erro ao guardar ficheiro + + Warning + Aviso - - An error occurred when saving <b>%1</b><br><br>Error: %2 - Ocorreu um erro ao guardar <b>%1</b><br><br>Erro: %2 + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + Esta funcionalidade é experimental e não deve ser considerada segura para trabalhos de importância crítica. Pode levar a uma possível perda de dados. Utilize-a por sua conta e risco. - - Zoom: %1% - Zoom: %1% + + <System Default> + <System Default> + + + QObject - - No updates are available at this time. - De momento, não há atualizações disponíveis. + + List All Tabs + Listar todos os separadores - - - PreferencesDialog - - Preferences - Preferências + + Detach Group + Retirar grupo - - Show menu bar - Mostrar barra de menus + + Minimize + Minimizar - - Show toolbar - Mostrar barra de ferramentas + + Close Tab + Fechar separador + + + QuickFindWidget - - Show status bar - Mostrar barra de estado + + Frame + Moldura - - Restore previous session - Restaurar a sessão anterior + + Match case + Corresponder minúsculas/maiúsculas - - Unsaved changes - Alterações não guardadas + + Aa + Aa - - Temporary files - Ficheiros temporários + + Match whole word + Corresponder palavra inteira - - Recenter find/replace dialog when opened - Recolocar a janela localizar/substituir quando aberta + + |A| + |A| - - Combine search results - Combinar resultados de pesquisa + + Use regular expression + Usar expressão regular - - Translation: - Tradução: + + . * + . * - - Exit on last tab closed - Sair no último separador fechado + + Alt+E + Alt+E - - Default Font - Tipo de letra predefinida + + Find... + Localizar... - - Font - Tipo de letra + + %L1/%L2 + %L1/%L2 + + + SearchResultsDock - - Font Size - Tamanho do tipo de letra + + Search Results + Resultados da pesquisa - - pt - pt + + Collapse All + Recolher tudo - - Default Line Endings - Finais de linha predefinidos + + Expand All + Expandir tudo - - Highlight URLs - Destacar URLs + + Delete Entry + Eliminar entrada - - Show Line Numbers - Mostrar números de linha + + Delete All + Eliminar tudo + + + Updater - - - Default Directory - + + Would you like to download the update now? + Quer descarregar a atualização agora? - - Follow Current Document - + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + Gostaria de descarregar a atualização agora? Esta é uma atualização obrigatória, sair agora fechará a aplicação - - Last Used Directory - + + Version %1 of %2 has been released! + A versão %1 de %2 foi lançada! - - ... - ... + + No updates are available for the moment + De momento, não há atualizações disponíveis - - TextLabel - Legenda + + Congratulations! You are running the latest version of %1 + Parabéns! Está a executar a versão mais recente do %1 + + + ads::CAutoHideTab - - An application restart is required to apply certain settings. - É necessário reiniciar a aplicação para aplicar determinadas definições. + + Detach + Retirar - - Warning - Aviso + + Pin To... + Fixar na... - - This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. - Esta funcionalidade é experimental e não deve ser considerada segura para trabalhos de importância crítica. Pode levar a uma possível perda de dados. Utilize-a por sua conta e risco. + + Top + Superior - - System Default - Predefinição do sistema + + Left + Esquerda - - Windows (CR LF) - Windows (CR LF) + + Right + Direita - - Linux (LF) - Linux (LF) + + Bottom + Inferior - - Macintosh (CR) - Macintosh (CR) + + Unpin (Dock) + Desafixar (Doca) - - <System Default> - <System Default> + + Close + Fechar - - - QuickFindWidget + + + ads::CDockAreaTitleBar - - Frame - Moldura + + Detach + Retirar - - Find... - Localizar... + + Detach Group + Retirar grupo - - Match case - Corresponder minúsculas/maiúsculas + + + Unpin (Dock) + Desafixar (Doca) - - Aa - Aa + + + Pin Group + Fixar grupo - - Match whole word - Corresponder palavra inteira + + Pin Group To... + Fixar grupo na... - - |A| - |A| + + Top + Superior - - Use regular expression - Usar expressão regular + + Left + Esquerda - - . * - . * + + Right + Direita - - Alt+E - Alt+E + + Bottom + Inferior - - %L1/%L2 - %L1/%L2 + + + Minimize + Minimizar + + + + + + Close + Fechar + + + + + Close Group + Fechar grupo + + + + Close Other Groups + Fechar outros grupos + + + + Pin Active Tab (Press Ctrl to Pin Group) + Fixar separadores ativos (Premir Ctrl para fixar grupo) + + + + Close Active Tab + Fechar separador ativo + + + + ads::CDockManager + + + Show View + Mostrar visualização + + + + ads::CDockWidgetTab + + + Detach + Retirar + + + + Pin + Fixar + + + + Pin To... + Fixar na... - - - SearchResultsDock - - Search Results - Resultados da pesquisa + + Top + Superior - - Copy Results to Clipboard - Copiar resultados para a área de transferência + + Left + Esquerda - - Collapse All - Recolher tudo + + Right + Direita - - Expand All - Expandir tudo + + Bottom + Inferior - - Delete Entry - Eliminar entrada + + Close + Fechar - - Delete All - Eliminar tudo + + Close Others + Fechar outros - + diff --git a/i18n/NotepadNext_ru_RU.ts b/i18n/NotepadNext_ru_RU.ts new file mode 100644 index 000000000..b20e03284 --- /dev/null +++ b/i18n/NotepadNext_ru_RU.ts @@ -0,0 +1,2421 @@ + + + + + ColumnEditorDialog + + + Column Mode + Режим столбцов + + + + Text + Текст + + + + Numbers + Числа + + + + Start: + Начало: + + + + Step: + Шаг: + + + + DebugLogDock + + + Debug Log + Журнал отладки + + + + Downloader + + + + Updater + + + + + + + Downloading updates + + + + + Time remaining: 0 minutes + + + + + Open + + + + + + Stop + + + + + + Time remaining + + + + + unknown + + + + + Error + + + + + Cannot find downloaded update! + + + + + Close + Закрыть + + + + Download complete! + + + + + The installer will open separately + + + + + Click "OK" to begin installing the update + + + + + In order to install the update, you may need to quit the application. + + + + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + + + + + Click the "Open" button to apply the update + + + + + Are you sure you want to cancel the download? + + + + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + + + + + + %1 bytes + + + + + + %1 KB + + + + + + %1 MB + + + + + of + + + + + Downloading Updates + + + + + Time Remaining + + + + + Unknown + + + + + about %1 hours + + + + + about one hour + + + + + %1 minutes + + + + + 1 minute + + + + + %1 seconds + + + + + 1 second + + + + + EditorInfoStatusBar + + + Length: %L1 Lines: %L2 + Длина: %L1 Строк: %L2 + + + + Sel: N/A + Выб: Н/Д + + + + Sel: %L1 | %L2 + Выб: %L1 | %L2 + + + + Ln: %L1 Col: %L2 + Стр: %L1 Стл: %L2 + + + + Macintosh (CR) + Macintosh (CR) + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + ANSI + ANSI + + + + UTF-8 + UTF-8 + + + + EditorInspectorDock + + + Editor Inspector + Инспектор редактора + + + + Position Information + Информация о положении + + + + Current Position + Текущее положение + + + + Current Position (x, y) + Текущее положение (x, y) + + + + Column + Столбец + + + + Current Style + Текущий стиль + + + + Current Line + Текущая строка + + + + Line Length + Длина строки + + + + Line End Position + Положение конца строки + + + + Line Indentation + Отступ строки + + + + Line Indent Position + Положение отступа строки + + + + Selection Information + Информация о выделении + + + + Mode + Режим + + + + Is Rectangle + Прямоугольник + + + + Selection Empty + Выделение пусто + + + + Main Selection + Основное выделение + + + + # of Selections + # выделений + + + + Multiple Selections + Множественные выделения + + + + Document Information + Информация о документе + + + + Length + Длина + + + + Line Count + Количество строк + + + + View Information + Сведения об области просмотра + + + + Lines on Screen + Строк на экране + + + + First Visible Line + Первая видимая строка + + + + X Offset + Смещение по X + + + + Fold Information + Информация о сворачивании + + + + Visible From Doc Line + Отображаемая от строки документа + + + + Doc Line From Visible + Строка документа от отображаемой + + + + Fold Level + Уровень вложенности + + + + Is Fold Header + Заголовок вложения + + + + Fold Parent + Родитель вложения + + + + Last Child + Последний дочерний + + + + Contracted Fold Next + Следующее свернутое вложение + + + + Caret + Каретка + + + + Anchor + Якорь + + + + Caret Virtual Space + Виртуальное пространство каретки + + + + Anchor Virtual Space + Виртуальное пространство якоря + + + + FileList + + + File List + Список файлов + + + + FindReplaceDialog + + + + + Find + Поиск + + + + Search Mode + Режим поиска + + + + &Normal + &Нормальный + + + + E&xtended (\n, \r, \t, \0, \x...) + Р&асширенный (\n, \r, \t, \0, \x...) + + + + Re&gular expression + &Регулярное выражение + + + + &. matches newline + &. - новая строка + + + + Transparenc&y + Про&зрачность + + + + On losing focus + При потере фокуса + + + + Always + Всегда + + + + Coun&t + &Подсчитать + + + + &Replace + &Заменить + + + + Replace &All + Заменить &все + + + + Replace All in &Opened Documents + Заменить все во всех о&ткрытых документах + + + + Find All in All &Opened Documents + Найти все во всех откр&ытых документах + + + + Find All in Current Document + Найти все в текущем документе + + + + Close + Закрыть + + + + &Find: + &Найти: + + + + Replace: + Заменить: + + + + Backward direction + Обратное направление поиска + + + + Match &whole word only + Только целые &слова + + + + Match &case + Учитывать &регистр + + + + Wra&p Around + За&циклить поиск + + + + Replace + Замена + + + + + Replaced %Ln matches + + Заменено %Ln соответствие + Заменено %Ln соответствия + Заменено %Ln соответствий + + + + + The end of the document has been reached. Found 1st occurrence from the top. + Достигнут конец документа. Обнаружено первое соответствие сверху. + + + + No matches found. + Не найдено соответствий. + + + + 1 occurrence was replaced + 1 совпадение заменено + + + + No more occurrences were found + Больше совпадений не обнаружено + + + + Found %Ln matches + + Найдено %Ln соответствие + Найдено %Ln соответствия + Найдено %Ln соответствий + + + + + FolderAsWorkspaceDock + + + Folder as Workspace + Папка как Проект + + + + HexViewerDock + + + Hex Viewer + Просмотр Hex + + + + LanguageInspectorDock + + + Language Inspector + Инспектор языка + + + + Language: + Язык: + + + + Lexer: + Лексер: + + + + Properties: + Свойства: + + + + Property + Свойство + + + + Type + Тип + + + + + Description + Описание + + + + Value + Значение + + + + Keywords: + Ключевые слова: + + + + ID + + + + + Styles: + Стили: + + + + TextLabel + + + + + Position %1 Style %2 + Положение %1 Стиль %2 + + + + LuaConsoleDock + + + Lua Console + Консоль Lua + + + + MacroEditorDialog + + + Macro Editor + Редактор макросов + + + + Name + Имя + + + + Shortcut + Комбинация клавиш + + + + Steps: + Шаги: + + + + Insert Macro Step + Вставить шаг макроса + + + + Delete Selected Macro Step + Удалить выбранный шаг макроса + + + + Move Selected Macro Step Up + Переместить выбранный шаг макроса вверх + + + + Move Selected Macro Step Down + Переместить выбранный шаг макроса вниз + + + + Copy Selected Macro + Копировать выбранный макрос + + + + Delete Selected Macro + Удалить выбранный макрос + + + + Delete Macro + Удалить макрос + + + + Are you sure you want to delete <b>%1</b>? + Вы действительно хотите удалить <b>%1</b>? + + + + (Copy) + (копия) + + + + MacroRunDialog + + + Run a Macro Multiple Times + Многократный запуск + + + + Macro: + Макрос: + + + + Run Until End of File + Выполнять до конца файла + + + + Execute... + Выполнить... + + + + times + раз(а) + + + + Run + Запускать + + + + Cancel + Отмена + + + + MacroSaveDialog + + + Save Macro + Сохранение макроса + + + + Name: + Имя: + + + + Shortcut: + Комбинация клавиш: + + + + OK + ОК + + + + Cancel + Отмена + + + + MacroStepTableModel + + + Name + Имя + + + + Text + Текст + + + + MainWindow + + + Notepad Next[*] + Notepad Next[*] + + + + + + + + + + + &File + &Файл + + + + Close More + Закрытие вкладок + + + + &Recent Files + &Последние файлы + + + + + Export As + Экспортировать как + + + + &Edit + &Правка + + + + Copy More + Копировать в буфер + + + + Indent + Отступ + + + + EOL Conversion + Конвертация конца строк + + + + Convert Case + Конвертация регистра + + + + Line Operations + Операции со строками + + + + Comment/Uncomment + Комментирование + + + + Copy As + Копировать как + + + + Encoding/Decoding + Кодирование/декодирование + + + + Search + Поиск + + + + Bookmarks + Закладки + + + + &View + &Вид + + + + &Zoom + &Масштаб + + + + Show Symbol + Показать символ + + + + Fold Level + Уровень вложенности + + + + Unfold Level + + + + + Language + Язык + + + + Settings + Опции + + + + Macro + Макросы + + + + Help + Справка + + + + Encoding + Кодировка + + + + Main Tool Bar + Основная панель инструментов + + + + &New + &Новый + + + + Create a new file + Создать новый файл + + + + Ctrl+N + + + + + &Open... + &Открыть... + + + + Ctrl+O + + + + + &Save + &Сохранить + + + + Save + Сохранить + + + + Ctrl+S + Ctrl+S + + + + E&xit + &Выход + + + + &Undo + &Отмена + + + + Ctrl+Z + Ctrl+Z + + + + &Redo + &Повтор + + + + Ctrl+Y + + + + + Cu&t + В&ырезать + + + + Ctrl+X + + + + + &Copy + &Копировать + + + + Ctrl+C + + + + + &Paste + В&ставить + + + + Ctrl+V + + + + + &Delete + &Удалить + + + + Del + Del + + + + Copy Full Path + Копировать полный путь + + + + Copy File Name + Копировать имя файла + + + + Copy File Directory + Копировать путь к файлу + + + + &Close + &Закрыть + + + + Close the current file + Закрыть текущий файл + + + + Ctrl+W + Ctrl+W + + + + Save &As... + Сох&ранить как... + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Save a Copy As... + Сохранить копию как... + + + + Sav&e All + Сохра&нить все + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Select A&ll + Выделить &все + + + + Ctrl+A + Ctrl+A + + + + Increase Indent + Увеличить отступ + + + + Decrease Indent + Уменьшить отступ + + + + Rename... + Переименовать... + + + + Re&load + &Перезагрузить + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + Macintosh (CR) + Macintosh (CR) + + + + UPPER CASE + ВЕРХНИЙ РЕГИСТР + + + + Convert text to upper case + Конвертировать текст в верхний регистр + + + + lower case + нижний регистр + + + + Convert text to lower case + Конвертировать текст в нижний регистр + + + + Duplicate Current Line + Дублировать текущую строку + + + + Alt+Down + + + + + Split Lines + Разбить строки + + + + Join Lines + Объединить строки + + + + Ctrl+J + Ctrl+J + + + + Move Selected Lines Up + Переместить выбранные строки вверх + + + + Ctrl+Shift+Up + Ctrl+Shift+Up + + + + Move Selected Lines Down + Переместить выбранные строки вниз + + + + Ctrl+Shift+Down + Ctrl+Shift+Down + + + + Clos&e All + Зак&рыть все + + + + Close All files + Закрыть все файлы + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Close All Except Active Document + Закрыть все кроме текущей + + + + Close All to the Left + Закрыть все вкладки слева + + + + Close All to the Right + Закрыть все вкладки справа + + + + Zoom &In + У&величить масштаб + + + + Ctrl++ + Ctrl++ + + + + Zoom &Out + &Уменьшить масштаб + + + + Ctrl+- + Ctrl+- + + + + Reset Zoom + Сбросить масштаб + + + + Ctrl+0 + Ctrl+0 + + + + About Qt + О Qt + + + + About Notepad Next + О Notepad Next + + + + Show Whitespace + Показывать пустое пространство + + + + Show End of Line + Показывать символ конца строки + + + + Show All Characters + Показывать все символы + + + + Show Indent Guide + Показывать направляющие отступов + + + + Show Wrap Symbol + Отображать знак Перенос строк + + + + Word Wrap + Перенос строк + + + + Restore Recently Closed File + Открыть последний закрытый файл + + + + Ctrl+Shift+T + + + + + Open All Recent Files + Открыть все недавние файлы + + + + Clear Recent Files List + Очистить список недавних файлов + + + + &Find... + &Найти... + + + + Ctrl+F + Ctrl+F + + + + Find in Files... + Найти в файлах... + + + + Find &Next + Искать &далее + + + + F3 + F3 + + + + Find &Previous + Искать &ранее + + + + &Replace... + &Заменить... + + + + Ctrl+H + Ctrl+H + + + + Full Screen + Полный экран + + + + F11 + F11 + + + + + Start Recording + Начать запись + + + + Playback + Воспроизвести + + + + Ctrl+Shift+P + Ctrl+Shift+ + + + + Save Current Recorded Macro... + Сохранить записанный макрос... + + + + Run a Macro Multiple Times... + Многократный запуск... + + + + Preferences... + Настройки... + + + + Quick Find + Быстрый поиск + + + + Ctrl+Alt+I + Ctrl+Alt+I + + + + Select Next Instance + Выделить следующий экземпляр + + + + Ctrl+D + Ctrl+D + + + + Move to Trash... + Убрать в корзину... + + + + Move to Trash + Убрать в корзину + + + + Check for Updates... + Проверить обновления... + + + + &Go to Line... + &Перейти к строке... + + + + Ctrl+G + Ctrl+G + + + + Print... + Печать... + + + + Ctrl+P + Ctrl+P + + + + Open Folder as Workspace... + Открыть папку как Проект... + + + + Toggle Single Line Comment + Комментирование строки (включить/выключить) + + + + Ctrl+/ + Ctrl+/ + + + + Single Line Comment + Комментировать строку + + + + Ctrl+K + Ctrl+K + + + + Single Line Uncomment + Раскомментировать строку + + + + Ctrl+Shift+K + Ctrl+Shift+K + + + + Edit Macros... + Редактирование макросов... + + + + This is not currently implemented + Это еще не реализовано + + + + Column Mode... + Режим столбцов... + + + + Export as HTML... + Экспортировать как HTML... + + + + Export as RTF... + Экспортировать как RTF... + + + + Copy as HTML + Копировать как HTML + + + + Copy as RTF + Копировать как RTF + + + + Base 64 Encode + Кодирование Base 64 + + + + URL Encode + Кодирование URL + + + + Base 64 Decode + Декодирование Base 64 + + + + URL Decode + Декодирование URL + + + + Copy URL + Копировать URL + + + + Remove Empty Lines + Удалить пустые строки + + + + + Show in Explorer + Открыть в Проводнике + + + + Open Command Prompt Here + Открыть Командную строку здесь + + + + Toggle Bookmark + Закладка (поставить/снять) + + + + Ctrl+F2 + Ctrl+F2 + + + + Next Bookmark + Следующая закладка + + + + F2 + F2 + + + + Previous Bookmark + Предыдущая закладка + + + + Shift+F2 + Shift+F2 + + + + Clear Bookmarks + Очистить закладки + + + + Invert Bookmarks + Инвертировать закладки + + + + Next Tab + + + + + Ctrl+Tab + + + + + Previous Tab + + + + + Ctrl+Shift+Tab + + + + + Fold Level 1 + + + + + Alt+1 + + + + + Fold Level 2 + + + + + Alt+2 + + + + + Fold Level 3 + + + + + Alt+3 + + + + + Fold Level 4 + + + + + Alt+4 + + + + + Unfold Level 1 + + + + + Alt+Shift+1 + + + + + Unfold Level 2 + + + + + Alt+Shift+2 + + + + + Unfold Level 3 + + + + + Alt+Shift+3 + + + + + Unfold Level 4 + + + + + Alt+Shift+4 + + + + + Fold All + + + + + Alt+0 + + + + + Unfold All + + + + + Alt+Shift+0 + + + + + Fold Level 5 + + + + + Alt+5 + + + + + Fold Level 6 + + + + + Alt+6 + + + + + Fold Level 7 + + + + + Alt+7 + + + + + Fold Level 8 + + + + + Alt+8 + + + + + Fold Level 9 + + + + + Alt+9 + + + + + Unfold Level 5 + + + + + Alt+Shift+5 + + + + + Unfold Level 6 + + + + + Alt+Shift+6 + + + + + Unfold Level 7 + + + + + Alt+Shift+7 + + + + + Unfold Level 8 + + + + + Alt+Shift+8 + + + + + Unfold Level 9 + + + + + Alt+Shift+9 + + + + + Go to line + Перейти к строке + + + + Line Number (1 - %1) + Номер строки (1 - %1) + + + + Stop Recording + Остановить запись + + + + New %1 + Новый %1 + + + + Create File + Создать файл + + + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> не существует. Хотите создать его? + + + + + Save file <b>%1</b>? + Сохранить файл <b>%1</b>? + + + + + Save File + Сохранить файл + + + + Open Folder as Workspace + Открыть папку как Проект + + + + Reload File + Перезагрузить файл + + + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + Уверены, что хотите перезагрузить <b>%1</b>? Все несохраненные изменения будут потеряны. + + + + Save a Copy As + Сохранить копию как + + + + + Rename + Переименовать + + + + Name: + Имя: + + + + Delete File + Удалить файл + + + + Are you sure you want to move <b>%1</b> to the trash? + Вы действительно хотите переместить <b>%1</b> в корзину? + + + + Error Deleting File + Ошибка при удалении файла + + + + Something went wrong deleting <b>%1</b>? + Что-то пошло не так при удалении <b>%1</b>? + + + + Administrator + Администратор + + + + Error Saving File + Ошибка при сохранении файла + + + + An error occurred when saving <b>%1</b><br><br>Error: %2 + Произошла ошибка при сохранении <b>%1</b><br><br>Ошибка: %2 + + + + Zoom: %1% + Масштаб: %1% + + + + No updates are available at this time. + В настоящее время обновлений нет. + + + + PreferencesDialog + + + Preferences + Настройки + + + + Show menu bar + Показать строку меню + + + + Show toolbar + Показать панель инструментов + + + + Show status bar + Показать строку состояния + + + + Restore previous session + Восстанавливать предыдущую сессию + + + + Unsaved changes + Несохраненные изменения + + + + Temporary files + Временные файлы + + + + Combine search results + Комбинировать результаты поиска + + + + Translation: + Перевод: + + + + Exit on last tab closed + + + + + Default Font + + + + + Font + + + + + Font Size + + + + + pt + + + + + TextLabel + TextLabel + + + + An application restart is required to apply certain settings. + Для применения определенных настроек требуется перезапуск приложения. + + + + Warning + Предупреждение + + + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + Эта функция является экспериментальной, и ее не следует считать безопасной для критически важной работы. Это может привести к возможной потере данных. Используйте на свой риск. + + + + <System Default> + <Использовать системный> + + + + QObject + + + List All Tabs + + + + + Detach Group + + + + + Minimize + + + + + Close Tab + + + + + QuickFindWidget + + + Frame + Фрейм + + + + Match case + Учитывать регистр + + + + Aa + Aa + + + + Match whole word + Искать целые слова + + + + |A| + |A| + + + + Use regular expression + Используйте регулярное выражение + + + + . * + . * + + + + Alt+E + Alt+E + + + + Find... + Поиск... + + + + %L1/%L2 + + + + + SearchResultsDock + + + Search Results + Результаты поиска + + + + Collapse All + Свернуть все + + + + Expand All + Развернуть все + + + + Delete Entry + Удалить запись + + + + Delete All + Удалить все + + + + Updater + + + Would you like to download the update now? + + + + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + + + + + Version %1 of %2 has been released! + + + + + No updates are available for the moment + + + + + Congratulations! You are running the latest version of %1 + + + + + ads::CAutoHideTab + + + Detach + + + + + Pin To... + + + + + Top + + + + + Left + + + + + Right + + + + + Bottom + + + + + Unpin (Dock) + + + + + Close + Закрыть + + + + ads::CDockAreaTitleBar + + + Detach + + + + + Detach Group + + + + + + Unpin (Dock) + + + + + + Pin Group + + + + + Pin Group To... + + + + + Top + + + + + Left + + + + + Right + + + + + Bottom + + + + + + Minimize + + + + + + + Close + Закрыть + + + + + Close Group + + + + + Close Other Groups + + + + + Pin Active Tab (Press Ctrl to Pin Group) + + + + + Close Active Tab + + + + + ads::CDockManager + + + Show View + + + + + ads::CDockWidgetTab + + + Detach + + + + + Pin + + + + + Pin To... + + + + + Top + + + + + Left + + + + + Right + + + + + Bottom + + + + + Close + Закрыть + + + + Close Others + + + + diff --git a/i18n/NotepadNext_sv_SE.ts b/i18n/NotepadNext_sv_SE.ts new file mode 100644 index 000000000..24feba873 --- /dev/null +++ b/i18n/NotepadNext_sv_SE.ts @@ -0,0 +1,2511 @@ + + + + + ColumnEditorDialog + + + Column Mode + Kolumnläge + + + + Text + Text + + + + Numbers + Siffror + + + + Start: + Start: + + + + Step: + Steg: + + + + DebugLogDock + + + Debug Log + Felsökningslogg + + + + Downloader + + + + Updater + Uppdaterare + + + + + + Downloading updates + Laddar ner uppdateringar + + + + Time remaining: 0 minutes + Återstående tid: 0 minuter + + + + Open + Öppna + + + + + Stop + Stopp + + + + + Time remaining + Återstående tid + + + + unknown + okänd + + + + Error + Fel + + + + Cannot find downloaded update! + Kan inte hitta nerladdad uppdatering! + + + + Close + Stäng + + + + Download complete! + Nerladdning slutförd! + + + + The installer will open separately + Installeraren öppnas separat + + + + Click "OK" to begin installing the update + Tryck "OK" för att installera uppdateringen + + + + In order to install the update, you may need to quit the application. + Du kanske måste avsluta programmet för att installera uppdateringen. + + + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + Du kanske måste avsluta programmet för att installera uppdateringen. Detta är en obligatorisk uppdatering, avslutar du nu. stängs programmet + + + + Click the "Open" button to apply the update + Tryck på "Öppna" för att tillämpa uppdateringen + + + + Are you sure you want to cancel the download? + Vill du verkligen avbryta nerladdningen? + + + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + Vill du verkligen avbryta nerladdningen? Detta är en obligatorisk uppdatering, avslutar du nu. stängs programmet + + + + + %1 bytes + %1 byte + + + + + %1 KB + %1 KB + + + + + %1 MB + %1 MB + + + + of + av + + + + Downloading Updates + Laddar ner uppdateringar + + + + Time Remaining + Återstående tid + + + + Unknown + Okänd + + + + about %1 hours + ca: %1 timmar + + + + about one hour + ca: 1 timma + + + + %1 minutes + %1 minuter + + + + 1 minute + 1 minut + + + + %1 seconds + %1 sekunder + + + + 1 second + 1 sekund + + + + EditorInfoStatusBar + + Length: %1 Lines: %2 + Längd: %1 Rader: %2 + + + + Sel: N/A + Markerat: Ej tillämpligt + + + Sel: %1 | %2 + Markerat: %1 | %2 + + + Ln: %1 Col: %2 + Rad: %1 Col: %2 + + + + Length: %L1 Lines: %L2 + Längd: %L1 Rader: %L2 + + + + Sel: %L1 | %L2 + Mark: %L1 | %L2 + + + + Ln: %L1 Col: %L2 + Rad: %L1 Kol: %L2 + + + + Macintosh (CR) + Macintosh (CR) + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + ANSI + ANSI + + + + UTF-8 + UTF-8 + + + + EditorInspectorDock + + + Editor Inspector + Redigeringsinspektör + + + + Current Position + Aktuell position + + + + Current Position (x, y) + Aktuell position (x, y) + + + + Column + Kolumn + + + + Current Style + Aktuell stil + + + + Current Line + Aktuell rad + + + + Line Length + Radlängd + + + + Line End Position + Radslutsposition + + + + Line Indentation + Radindrag + + + + Line Indent Position + Radindragsposition + + + + Selection Information + Markeringsinformation + + + + Is Rectangle + Är rektangel + + + + Selection Empty + Markering tom + + + + Main Selection + Huvudsaklig markering + + + + # of Selections + # av markerat + + + + Multiple Selections + Flera markeringar + + + + Document Information + Dokumentinformation + + + + Position Information + Positionsinformation + + + + Mode + Läge + + + + Length + Längd + + + + Line Count + Radantal + + + + View Information + Visa information + + + + Lines on Screen + Rader på skärmen + + + + First Visible Line + Första synliga rad + + + + X Offset + X-förskjutning + + + + Fold Information + Radbrytningsinformation + + + + Visible From Doc Line + Synlig från dokumentrad + + + + Doc Line From Visible + Dokumentrad från synlig + + + + Fold Level + Radbrytningsnivå + + + + Is Fold Header + Är radbrytningsrubrik + + + + Fold Parent + Radbryt överordnad + + + + Last Child + Senast underordnad + + + + Contracted Fold Next + Kontrakterad radbryt nästa + + + + Caret + Textmarkör + + + + Anchor + Ankare + + + + Caret Virtual Space + Virtuellt avstånd för textmarkör + + + + Anchor Virtual Space + Virtuellt avstånd för ankare + + + + FileList + + + File List + Fillista + + + + FindReplaceDialog + + + + + Find + Sök + + + + Search Mode + Sökläge + + + + &Normal + &Normal + + + + E&xtended (\n, \r, \t, \0, \x...) + &Utökat (\n, \r, \t, \0, \x...) + + + + Re&gular expression + &Regular expression + + + + &. matches newline + &. matchar ny rad + + + + Transparenc&y + &Transparens + + + + On losing focus + Vid förlorat fokus + + + + Always + Alltid + + + + Coun&t + &Räkna + + + + &Replace + &Ersätt + + + + Replace &All + Ersätt &alla + + + + Replace All in &Opened Documents + Ersätt alla i &öppna dokument + + + + Find All in All &Opened Documents + Sök alla i &öppna dokument + + + + Find All in Current Document + Sök alla i aktuellt dokument + + + + Close + Stäng + + + + &Find: + &Sök: + + + + Replace: + Ersätt: + + + &Find what: + &Sök vad: + + + Replace with: + Ersätt med: + + + + Backward direction + Bakåtriktning + + + + Match &whole word only + Matcha endast &hela ord + + + + Match &case + Matcha &skiftläge + + + + Wra&p Around + &Radbryt + + + + Replace + Ersätt + + + Replaced %L1 matches + Ersatte %L1 träffar + + + + + Replaced %Ln matches + + Ersatte %Ln träff + Ersatte %Ln träffar + + + + + The end of the document has been reached. Found 1st occurrence from the top. + Slutet på dokumentet har nåtts. Hittade 1:a förekomsten från toppen. + + + + No matches found. + Inga träffar. + + + + 1 occurrence was replaced + 1 förekomst ersattes + + + + No more occurrences were found + Inga fler förekomster hittades + + + + Found %Ln matches + + Hittade %Ln träff + Hittade %Ln träffar + + + + Found %L1 matches + Hittade %L1 träffar + + + Replaced %1 matches + %1 ersattes + + + Found %1 matches + %1 träff(ar) + + + + FolderAsWorkspaceDock + + + Folder as Workspace + Mapp som arbetsyta + + + + HexViewerDock + + + Hex Viewer + Hexläsare + + + + LanguageInspectorDock + + + Language Inspector + Språkinspektör + + + + Language: + Språk: + + + + Lexer: + Lexer: + + + + Properties: + Egenskaper: + + + + Property + Egenskap + + + + Type + Typ + + + + + Description + Beskrivning + + + + Value + Värde + + + + Keywords: + Nyckelord: + + + + ID + ID + + + + Styles: + Stilar: + + + + TextLabel + TextEtikett + + + Postion %1 Style %2 + Position %1 Stil %2 + + + + Position %1 Style %2 + Position %1 Stil %2 + + + + LuaConsoleDock + + + Lua Console + Lua-konsol + + + + MacroEditorDialog + + + Macro Editor + Makroredigerare + + + + Name + Namn + + + + Shortcut + Genväg + + + + Steps: + Steg: + + + + Insert Macro Step + Infoga makrosteg + + + + Delete Selected Macro Step + Ta bort markerat makrosteg + + + + Move Selected Macro Step Up + Flytta upp markerat makrosteg + + + + Move Selected Macro Step Down + Flytta ner markerat makrosteg + + + + Copy Selected Macro + Kopiera markerat makrosteg + + + + Delete Selected Macro + Ta bort markerat makrosteg + + + + Delete Macro + Ta bort makro + + + + Are you sure you want to delete <b>%1</b>? + Vill du verkligen ta bort <b>%1</b>? + + + + (Copy) + (Kopia) + + + + MacroRunDialog + + + Run a Macro Multiple Times + Kör ett makro flera gånger + + + + Macro: + Makro: + + + + Run Until End of File + Kör till slutet på filen + + + + Execute... + Exekvera... + + + + times + gånger + + + + Run + Kör + + + + Cancel + Avbryt + + + + MacroSaveDialog + + Dialog + Dialog + + + + Save Macro + Spara makro + + + + Name: + Namn: + + + + Shortcut: + Genväg: + + + + OK + OK + + + + Cancel + Avbryt + + + + MacroStepTableModel + + + Name + Namn + + + + Text + Text + + + + MainWindow + + + Notepad Next[*] + Notepad Next[*] + + + + + + + + + + + &File + &Arkiv + + + + Close More + Stäng mer + + + + &Recent Files + &Tidigare filer + + + + &Edit + &Redigera + + + + Copy More + Kopiera mer + + + + Indent + Indrag + + + + EOL Conversion + EOL-konvertering + + + + Convert Case + Konvertera skiftläge + + + + Line Operations + Radoperationer + + + + Comment/Uncomment + Kommentera/Avkommentera + + + + Search + Sök + + + + &View + &Visa + + + + &Zoom + &Zoom + + + + Show Symbol + Visa symbol + + + + Language + Språk + + + + Settings + Inställningar + + + + Macro + Makro + + + + Help + Hjälp + + + + Encoding + Kodning + + + Run + Kör + + + + Main Tool Bar + Verktygsfält + + + + &New + &Nytt + + + + Create a new file + Skapa en ny fil + + + + Ctrl+N + Ctrl+N + + + + &Open... + &Öppna... + + + + Ctrl+O + Ctrl+O + + + + &Save + &Spara + + + + Save + Spara + + + + Ctrl+S + Ctrl+S + + + + E&xit + A&vsluta + + + Alt+F4 + Alt+F4 + + + + &Undo + &Ångra + + + + Ctrl+Z + Ctrl+Z + + + + &Redo + &Upprepa + + + + Ctrl+Y + Ctrl+Y + + + + Cu&t + Kli&pp ut + + + + Ctrl+X + Ctrl+X + + + + &Copy + &Kopiera + + + + Ctrl+C + Ctrl+C + + + + &Paste + Klistra &in + + + + Ctrl+V + Ctrl+V + + + + &Delete + &Ta bort + + + + Del + Del + + + + Copy Full Path + Kopiera fullständig sökväg + + + + Copy File Name + Kopiera filnamn + + + + Copy File Directory + Kopiera filens mappnamn + + + + &Close + St&äng + + + + Close the current file + Stäng aktuell fil + + + + Ctrl+W + Ctrl+W + + + + Save &As... + Spara s&om... + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Save a Copy As... + Spara en kopia som... + + + + Sav&e All + Spa&ra alla + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Select A&ll + &Markera alla + + + + Ctrl+A + Ctrl+A + + + + Increase Indent + Öka indrag + + + + Decrease Indent + Minska indrag + + + + Rename... + Byt namn... + + + + Re&load + &Läs om från disk + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + Macintosh (CR) + Macintosh (CR) + + + + UPPER CASE + VERSALER + + + + Convert text to upper case + Konvertera text till VERSALER + + + + lower case + gemener + + + + Convert text to lower case + Konvertera text till gemener + + + + Duplicate Current Line + Duplicera aktuell rad + + + + Alt+Down + Alt+Nerpil + + + + Split Lines + Dela rader + + + + Join Lines + Sammanfoga rader + + + + Ctrl+J + Ctrl+J + + + + Move Selected Lines Up + Flytta markerade rader uppåt + + + + Ctrl+Shift+Up + Ctrl+Shift+Up + + + + Move Selected Lines Down + Flytta markerade rader neråt + + + + Ctrl+Shift+Down + Ctrl+Shift+Down + + + + Clos&e All + S&täng alla + + + + Close All files + Stäng alla filer + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Close All Except Active Document + Stäng alla utom aktivt dokument + + + + Close All to the Left + Stäng alla till vänster + + + + Close All to the Right + Stäng alla till höger + + + + Zoom &In + Zooma &in + + + + Ctrl++ + Ctrl++ + + + + Zoom &Out + Zooma &ut + + + + Ctrl+- + Ctrl+- + + + + Reset Zoom + Återställ zoom + + + + Ctrl+0 + Ctrl+0 + + + + Toggle Single Line Comment + Växla utkommentering + + + + Ctrl+/ + Ctrl+/ + + + + Single Line Comment + Kommentera ut enkelrad + + + + Ctrl+K + Ctrl+K + + + + Single Line Uncomment + Ta bort utkommentering + + + + Ctrl+Shift+K + Ctrl+Shift+K + + + + Edit Macros... + Redigera makron... + + + + This is not currently implemented + Detta är ännu inte implementerat + + + + Column Mode... + Kolumnläge... + + + + Next Tab + Nästa flik + + + + Ctrl+Tab + Ctrl+Tab + + + + Previous Tab + Föregående flik + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Fold Level 1 + Komprimera nivå 1 + + + + Alt+1 + Alt+1 + + + + Fold Level 2 + Komprimera nivå 2 + + + + Alt+2 + Alt+2 + + + + Fold Level 3 + Komprimera nivå 3 + + + + Alt+3 + Alt+3 + + + + Fold Level 4 + Komprimera nivå 4 + + + + Alt+4 + Alt+4 + + + + Unfold Level 1 + Expandera nivå 1 + + + + Alt+Shift+1 + Alt+Shift+1 + + + + Unfold Level 2 + Expandera nivå 2 + + + + Alt+Shift+2 + Alt+Shift+2 + + + + Unfold Level 3 + Expandera nivå 3 + + + + Alt+Shift+3 + Alt+Shift+3 + + + + Unfold Level 4 + Expandera nivå 4 + + + + Alt+Shift+4 + Alt+Shift+4 + + + + Fold All + Komprimera alla + + + + Alt+0 + Alt+0 + + + + Unfold All + Expandera alla + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Fold Level 5 + Komprimera nivå 5 + + + + Alt+5 + Alt+5 + + + + Fold Level 6 + Komprimera nivå 6 + + + + Alt+6 + Alt+6 + + + + Fold Level 7 + Komprimera nivå 7 + + + + Alt+7 + Alt+7 + + + + Fold Level 8 + Komprimera nivå 8 + + + + Alt+8 + Alt+8 + + + + Fold Level 9 + Komprimera nivå 9 + + + + Alt+9 + Alt+9 + + + + Unfold Level 5 + Expandera nivå 5 + + + + Alt+Shift+5 + Alt+Shift+5 + + + + Unfold Level 6 + Expandera nivå 6 + + + + Alt+Shift+6 + Alt+Shift+6 + + + + Unfold Level 7 + Expandera nivå 7 + + + + Alt+Shift+7 + Alt+Shift+7 + + + + Unfold Level 8 + Expandera nivå 8 + + + + Alt+Shift+8 + Alt+Shift+8 + + + + Unfold Level 9 + Expandera nivå 9 + + + + Alt+Shift+9 + Alt+Shift+9 + + + Alt+C + Alt+C + + + + Export as HTML... + Exportera som HTML... + + + + Export as RTF... + Exportera som RTF... + + + + Copy as HTML + Kopiera som HTML + + + + Copy as RTF + Kopiera som RTF + + + + Base 64 Encode + Base 64-koda + + + + URL Encode + URL-koda + + + + Base 64 Decode + Base 64-avkoda + + + + URL Decode + URL-avkoda + + + + Copy URL + Kopiera URL + + + + Remove Empty Lines + Ta bort tomma rader + + + + + Show in Explorer + Visa i filhanteraren + + + + Open Command Prompt Here + Öppna kommandotolken här + + + + Toggle Bookmark + Bokmärke på/av + + + + Ctrl+F2 + Ctrl+F2 + + + + Next Bookmark + Nästa bokmärke + + + + F2 + F2 + + + + Previous Bookmark + Föregående bokmärke + + + + Shift+F2 + Shift+F2 + + + + Clear Bookmarks + Ta bort bokmärken + + + + Invert Bookmarks + Invertera bokmärken + + + + About Qt + Om Qt + + + + + Export As + Exportera som + + + + Copy As + Kopiera som + + + + Encoding/Decoding + Kodning/Avkodning + + + + Bookmarks + Bokmärken + + + + Fold Level + Komprimeringsnivå + + + + Unfold Level + Expansionsnivå + + + + About Notepad Next + Om Notepad Next + + + + Show Whitespace + Visa blanksteg + + + + Show End of Line + Visa radslut + + + + Show All Characters + Visa alla tecken + + + + Show Indent Guide + Visa indragsguide + + + + Show Wrap Symbol + Visa radbrytningssymbol + + + + Word Wrap + Ordbrytning + + + + Restore Recently Closed File + Återställ tidigare stängda filer + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + Open All Recent Files + Öppna alla tidigare filer + + + + Clear Recent Files List + Rensa listan + + + + &Find... + &Sök... + + + + Ctrl+F + Ctrl+F + + + + Find in Files... + Sök i filer... + + + + Find &Next + Sök &nästa + + + + F3 + F3 + + + + Find &Previous + Sök &föregående + + + + &Replace... + &Ersätt... + + + + Ctrl+H + Ctrl+H + + + + Full Screen + Helskärm + + + + F11 + F11 + + + + + Start Recording + Starta inspelning + + + + Playback + Uppspelning + + + + Ctrl+Shift+P + Ctrl+Shift+P + + + + Save Current Recorded Macro... + Spara inspelat makro... + + + + Run a Macro Multiple Times... + Kör ett makro flera gånger... + + + Windows... + Fönster... + + + + Preferences... + Preferenser... + + + + Quick Find + Snabbsök + + + + Ctrl+Alt+I + Ctrl+Alt+I + + + + Select Next Instance + Välj nästa instans + + + + Ctrl+D + Ctrl+D + + + + Move to Trash... + Flytta till papperskorgen... + + + + Move to Trash + Flytta till papperskorgen + + + + Check for Updates... + Sök efter uppdateringar... + + + + &Go to Line... + &Gå till rad... + + + + Ctrl+G + Ctrl+G + + + + Print... + Skriv ut... + + + + Ctrl+P + Ctrl+P + + + + Open Folder as Workspace... + Öppen mapp som arbetsyta... + + + + Go to line + Gå till rad + + + + Line Number (1 - %1) + Radnummer (1 - %1) + + + + Stop Recording + Stoppa inspelning + + + + New %1 + Ny %1 + + + + Create File + Skapa fil + + + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> finns inte. Vill du skapa den? + + + + + Save file <b>%1</b>? + Vill du spara <b>%1</b>? + + + + + Save File + Spara fil + + + + Open Folder as Workspace + Öppen mapp som arbetsyta + + + + Reload File + Läs om fil + + + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + Vill du verkligen läsa om <b>%1</b> från disk? Alla osparade ändringar kommer att förloras. + + + + Administrator + Administratör + + + + Error Saving File + Kunde inte spara fil + + + + Save a Copy As + Spara en kopia som + + + + + Rename + Byt namn + + + + Name: + Namn: + + + + Delete File + Ta bort fil + + + + Are you sure you want to move <b>%1</b> to the trash? + Vill du verkligen flytta <b>%1</b> till papperskorgen? + + + + Error Deleting File + Kunde inte ta bort fil + + + + Something went wrong deleting <b>%1</b>? + Gick något fel vid borttagning av <b>%1</b>? + + + + An error occurred when saving <b>%1</b><br><br>Error: %2 + Ett fel uppstod när <b>%1</b> skulle sparas.<br><br>Fel: %2 + + + + Zoom: %1% + Zoom: %1% + + + + No updates are available at this time. + Inga uppdateringar tillgängliga den här gången. + + + No updates are availale at this time. + Inga uppdateringar tillgängliga den här gången. + + + + PreferencesDialog + + + Preferences + Preferenser + + + + Show menu bar + Visa menyfält + + + + Show toolbar + Visa verktygsfält + + + + Show status bar + Visa statusfält + + + + Restore previous session + Återställ föregående session + + + + Temporary files + Temporära filer + + + + Translation: + Översättning: + + + + Exit on last tab closed + Avsluta när sista fliken stängs + + + + Default Font + Standardteckensnitt + + + + Font + Teckensnitt + + + + Font Size + Teckenstorlek + + + + pt + pt + + + + TextLabel + TextEtikett + + + + An application restart is required to apply certain settings. + En programomstart krävs för att tillämpa vissa inställningar. + + + Menu Bar + Menyfält + + + Tool Bar + Verktygsfält + + + Status Bar + Statusfält + + + Restore Previous Session + Återställ föregående session + + + + Unsaved changes + Osparade ändringar + + + Temp Files + Temp-filer + + + + Combine search results + Kombinera sökresultat + + + + Warning + Varning + + + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + Denna funktion är experimentell och den bör inte betraktas som säker för kritiskt viktigt arbete. Det kan leda till eventuell dataförlust. Används på egen risk. + + + + <System Default> + <Systemstandard> + + + + QObject + + + List All Tabs + Lista alla flikar + + + + Detach Group + Koppla från grupp + + + + Minimize + Minimera + + + Close Active Tab + Stäng aktiv flik + + + Close Group + Stäng grupp + + + + Close Tab + Stäng flik + + + + QuickFindWidget + + + Frame + Ram + + + + Match case + Matcha skiftläge + + + + Aa + Aa + + + + Match whole word + Matcha hela ord + + + + |A| + |A| + + + + Use regular expression + Använd regular expression + + + + . * + . * + + + + Alt+E + Alt+E + + + + Find... + Sök... + + + + %L1/%L2 + %L1/%L2 + + + + SearchResultsDock + + + Search Results + Sökresultat + + + + Collapse All + Minimera alla + + + + Expand All + Expandera alla + + + + Delete Entry + Ta bort post + + + + Delete All + Ta bort alla + + + + Updater + + + Would you like to download the update now? + Vill du ladda ner uppdateringen nu? + + + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + Vill du ladda ner uppdateringen nu? Detta är en obligatorisk uppdatering, avslutar du nu. stängs programmet + + + + Version %1 of %2 has been released! + Version %1 av %2 har publicerats! + + + + No updates are available for the moment + Inga uppdateringar tillgängliga för tillfället + + + + Congratulations! You are running the latest version of %1 + Grattis! Du kör den senaste versionen av %1 + + + + ads::CAutoHideTab + + + Detach + Koppla ifrån + + + + Pin To... + Fäst vid... + + + + Top + Överkant + + + + Left + Vänsterkant + + + + Right + Högerkant + + + + Bottom + Underkant + + + + Unpin (Dock) + Lösgör (Docka) + + + + Close + Stäng + + + + ads::CDockAreaTitleBar + + + Detach Group + Koppla från grupp + + + + Detach + Koppla från + + + + + Unpin (Dock) + Lösgör (Docka) + + + + + Pin Group + Fäst grupp + + + + Pin Group To... + Fäst grupp vid... + + + + Top + Överkant + + + + Left + Vänsterkant + + + + Right + Högerkant + + + + Bottom + Underkant + + + + + Minimize + Minimera + + + + + + Close + Stäng + + + + + Close Group + Stäng grupp + + + + Close Other Groups + Stäng andra grupper + + + + Pin Active Tab (Press Ctrl to Pin Group) + Fäst aktiv flik (Tryck Ctrl för att fäst grupp) + + + + Close Active Tab + Stäng aktiv flik + + + + ads::CDockManager + + + Show View + Visningsvy + + + + ads::CDockWidgetTab + + + Detach + Koppla från + + + + Pin + Fäst + + + + Pin To... + Fäst vid... + + + + Top + Överkant + + + + Left + Vänsterkant + + + + Right + Högerkant + + + + Bottom + Underkant + + + + Close + Stäng + + + + Close Others + Stäng andra + + + diff --git a/i18n/NotepadNext_tr_TR.ts b/i18n/NotepadNext_tr_TR.ts new file mode 100644 index 000000000..b7f99dbbe --- /dev/null +++ b/i18n/NotepadNext_tr_TR.ts @@ -0,0 +1,2454 @@ + + + + + ColumnEditorDialog + + + Column Mode + Sütun Modu + + + + Text + Metin + + + + Numbers + Sayılar + + + + Start: + Başlangıç: + + + + Step: + Basamak: + + + + DebugLogDock + + + Debug Log + Hata Ayıklama Günlüğü + + + + Downloader + + + + Updater + Güncelleyici + + + + + + Downloading updates + Güncellemeler indiriliyor + + + + Time remaining: 0 minutes + Kalan süre: 0 dakika + + + + Open + + + + + + Stop + Durdur + + + + + Time remaining + Kalan Zaman + + + + unknown + bilinmiyor + + + + Error + Hata + + + + Cannot find downloaded update! + İndirilen güncelleme bulunamıyor! + + + + Close + Kapat + + + + Download complete! + İndirme tamamlandı! + + + + The installer will open separately + Yükleyici ayrı olarak açılacak + + + + Click "OK" to begin installing the update + Güncellemeyi yüklemeye başlamak için "Tamam "a tıklayın + + + + In order to install the update, you may need to quit the application. + Güncellemeyi yüklemek için uygulamadan çıkmanız gerekebilir. + + + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + Güncellemeyi yüklemek için uygulamadan çıkmanız gerekebilir. Bu zorunlu bir güncellemedir, şimdi çıkmak uygulamayı kapatacaktır + + + + Click the "Open" button to apply the update + Güncellemeyi uygulamak için "Aç" düğmesine tıklayın + + + + Are you sure you want to cancel the download? + İndirmeyi iptal etmek istediğinizden emin misiniz? + + + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + İndirmeyi iptal etmek istediğinizden emin misiniz? Bu zorunlu bir güncellemedir, şimdi çıkmak uygulamayı kapatacaktır + + + + + %1 bytes + %1 btye + + + + + %1 KB + %1 KB + + + + + %1 MB + %1 MB + + + + of + This thing is impossible to translate to Turkish without changing the whole scheme. It supposed to be "totalSize + tr("of")+ receivedSize" So I'm justing living it blank + + + + + Downloading Updates + Güncellemeler indiriliyor + + + + Time Remaining + Kalan Zaman + + + + Unknown + Bilinmiyor + + + + about %1 hours + yaklaşık %1 saat + + + + about one hour + yaklaşık bir saat + + + + %1 minutes + %1 dakika + + + + 1 minute + 1 dakika + + + + %1 seconds + %1 saniye + + + + 1 second + 1 saniye + + + + EditorInfoStatusBar + + + Length: %L1 Lines: %L2 + Uzunluk: %L1 Satır: %L2 + + + + Sel: N/A + Seçiml: N/A + + + + Sel: %L1 | %L2 + Seçim: %L1 | %L2 + + + + Ln: %L1 Col: %L2 + Satır: %L1 Sutun: %L2 + + + + Macintosh (CR) + Macintosh (CR) + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + ANSI + ANSI + + + + UTF-8 + UTF-8 + + + + EditorInspectorDock + + + Editor Inspector + Düzenleyici Denetleyicisi + + + + Position Information + Konum Bilgisi + + + + Current Position + Mevcut Konum + + + + Current Position (x, y) + Mevcut Konum (x, y) + + + + Column + Sütun + + + + Current Style + Mevcut Stil + + + + Current Line + Mevcut Satır + + + + Line Length + Satır Uzunluğu + + + + Line End Position + Satır Sonu Konumu + + + + Line Indentation + Satır Girintisi + + + + Line Indent Position + Satır Girinti Konumu + + + + Selection Information + Seçim Bilgisi + + + + Mode + Mod + + + + Is Rectangle + Dikdörtgen Seçim + + + + Selection Empty + Seçim Boş + + + + Main Selection + Ana Seçim + + + + # of Selections + Seçim Sayısı + + + + Multiple Selections + Birden Fazla Seçim + + + + Document Information + Belge Bilgisi + + + + Length + Uzunluk + + + + Line Count + Satır Sayısı + + + + View Information + Bilgileri Göster + + + + Lines on Screen + Ekrandaki Satırlar + + + + First Visible Line + İlk Görünen Satır + + + + X Offset + X Offset + + + + Fold Information + Katlama Bilgisi + + + + Visible From Doc Line + Belge Satırından Görünen + + + + Doc Line From Visible + Görünenden Belge Satırı + + + + Fold Level + Katlama Seviyesi + + + + Is Fold Header + Is Fold Header + + + + Fold Parent + Fold Parent + + + + Last Child + Last Child + + + + Contracted Fold Next + Contracted Fold Next + + + + Caret + İmleç + + + + Anchor + Bağlantı Noktası (Anchor) + + + + Caret Virtual Space + İmleç Sanal Boşluğu + + + + Anchor Virtual Space + Bağlantı Noktası (Anchor) Sanal Boşluğu + + + + FileList + + + File List + Dosya Listesi + + + + FindReplaceDialog + + + + + Find + Bul + + + + Search Mode + Arama Modu + + + + &Normal + &Normal + + + + E&xtended (\n, \r, \t, \0, \x...) + G&eliştirilmiş (\n, \r, \t, \0, \x..) + + + + Re&gular expression + RE&GEX + + + + &. matches newline + &. satırsonu satırıyla eşleşir + + + + Transparenc&y + Şeffaflı&k + + + + On losing focus + Fokus kaybolduğunda + + + + Always + Her Zaman + + + + Coun&t + Sa&y + + + + &Replace + &Değiştir + + + + Replace &All + &Tümünü Değiştir + + + + Replace All in &Opened Documents + &Açık Olan Tüm Dosyalardakileri Değiştir + + + + Find All in All &Opened Documents + &Açık Olan Tüm Dosyalardakileri Bul + + + + Find All in Current Document + Aktif Dosyadaki Hepsini Bul + + + + Close + Kapat + + + + &Find: + &Değiştir: + + + + Replace: + Değiştir: + + + + Backward direction + Geriye doğru yön + + + + Match &whole word only + Sadece &tüm kelimeyi eşleştir + + + + Match &case + Eşleşme &durumu + + + + Wra&p Around + E&trafını Sat + + + + Replace + Değiştir + + + + + Replaced %Ln matches + + %Ln eşleşme değiştirildi + + + + + The end of the document has been reached. Found 1st occurrence from the top. + Belgenin sonuna ulaşıldı. Üstten 1. eşleşme bulundu. + + + + No matches found. + Eşleşme Bulunamadı. + + + + 1 occurrence was replaced + 1 eşleşen değiştirildi + + + + No more occurrences were found + Başka eşleşen bulunamadı + + + + Found %Ln matches + + %Ln eşleşme bulundu + + + + + FolderAsWorkspaceDock + + + Folder as Workspace + Çalışma Alanı olarak Klasör + + + + HexViewerDock + + + Hex Viewer + Hex Görüntüleyicisi + + + + LanguageInspectorDock + + + Language Inspector + Dil Kontrolcüsü + + + + Language: + Dil: + + + + Lexer: + Lexer: + + + + Properties: + Özellikler: + + + + Property + + + + + Type + + + + + + Description + + + + + Value + + + + + Keywords: + Anahtar Kelimeler: + + + + ID + + + + + Styles: + Stiller: + + + + TextLabel + Metin + + + + Position %1 Style %2 + Pozisyon %1 Stil %2 + + + + LuaConsoleDock + + + Lua Console + Lua Konsolu + + + + MacroEditorDialog + + + Macro Editor + Makro Düzenleyicisi + + + + Name + İsim + + + + Shortcut + Kısayol + + + + Steps: + Adımlar: + + + + Insert Macro Step + Makro Adımları Ekle + + + + Delete Selected Macro Step + Seçilen Makro Adımınıı Sil + + + + Move Selected Macro Step Up + Seçilen Makro Adımını Yukarı Al + + + + Move Selected Macro Step Down + Seçilen Makro Adımını Aşağı Al + + + + Copy Selected Macro + Seçilen Makroyu Kopyala + + + + Delete Selected Macro + Seçilen Makroyu Sil + + + + Delete Macro + Makroyu Sil + + + + Are you sure you want to delete <b>%1</b>? + <b>%1</b>'i silmek istediğinize emin misiniz? + + + + (Copy) + (Kopyala) + + + + MacroRunDialog + + + Run a Macro Multiple Times + Makroyu bir çok kez çalıştır + + + + Macro: + Makro: + + + + Run Until End of File + Dosya sonuna kadar çalıştır + + + + Execute... + Çalıştır... + + + + times + kez + + + + Run + Başlat + + + + Cancel + İptal + + + + MacroSaveDialog + + + Save Macro + Makroyu Kaydet + + + + Name: + İsim: + + + + Shortcut: + Kısayol: + + + + OK + TAMAM + + + + Cancel + İptal + + + + MacroStepTableModel + + + Name + İsim + + + + Text + Metin + + + + MainWindow + + + Notepad Next[*] + Notepad Next[*] + + + + + + + + + + + &File + &Dosya + + + + Close More + Daha Fazlasını Kapat + + + + &Recent Files + &Son Dosyalar + + + + + Export As + ... olarak Dışa Aktar + + + + &Edit + &Düzenle + + + + Copy More + Daha Fazlasını Kopyala + + + + Indent + Girinti + + + + EOL Conversion + Satır Sonu Dönüşümü + + + + Convert Case + Büyük/Küçük Harf Dönüştür + + + + Line Operations + Satır İşlemleri + + + + Comment/Uncomment + Yorum Ekle/Kaldır + + + + Copy As + ... olarak Kopyala + + + + Encoding/Decoding + Kodlama/Çözme + + + + Search + Ara + + + + Bookmarks + Yer İmleri + + + + &View + &Görüntü + + + + &Zoom + &Yakınlaştırma + + + + Show Symbol + Sembolu Göster + + + + Fold Level + Katlama Seviyesi + + + + Unfold Level + + + + + Language + Dil + + + + Settings + Ayarlar + + + + Macro + Makro + + + + Help + Yardım + + + + Encoding + Kodlama + + + + Main Tool Bar + Ana Araç Çubuğu + + + + &New + &Yeni + + + + Create a new file + Yeni bir dosya oluştur + + + + Ctrl+N + Ctrl+N + + + + &Open... + &Aç... + + + + Ctrl+O + Ctrl+O + + + + &Save + &Kaydet + + + + Save + Kaydet + + + + Ctrl+S + Ctrl+S + + + + E&xit + Ç&ıkış + + + Alt+F4 + Alt+F4 + + + + &Undo + &Geri Al + + + + Ctrl+Z + Ctrl+Z + + + + &Redo + &Yinele + + + + Ctrl+Y + Ctrl+Y + + + + Cu&t + Ke&s + + + + Ctrl+X + Ctrl+X + + + + &Copy + &Kopyala + + + + Ctrl+C + Ctrl+C + + + + &Paste + &Yapıştır + + + + Ctrl+V + Ctrl+V + + + + &Delete + &Sil + + + + Del + Sil + + + + Copy Full Path + Tam Yolu Kopyala + + + + Copy File Name + Dosya Adını Kopyala + + + + Copy File Directory + Dosya Dizinini Kopyala + + + + &Close + &Kapat + + + + Close the current file + Mevcut dosyayı kapat + + + + Ctrl+W + Ctrl+W + + + + Save &As... + &Farklı olarak kaydet... + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Save a Copy As... + Bir Kopyayı Farklı Kaydet... + + + + Sav&e All + Hep&sini Kaydet + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Select A&ll + H&epsini Seç + + + + Ctrl+A + Ctrl+A + + + + Increase Indent + Girintiyi Artır + + + + Decrease Indent + Girintiyi Azalt + + + + Rename... + Yeniden Adlandır... + + + + Re&load + Ye&niden Yükle + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + Macintosh (CR) + Macintosh (CR) + + + + UPPER CASE + BÜYÜK HARF + + + + Convert text to upper case + Metni büyük harfe dönüştür + + + + lower case + küçük harf + + + + Convert text to lower case + Metni küçük harfe dönüştür + + + + Duplicate Current Line + Mevcut Satırı Çoğalt + + + + Alt+Down + Alt+Down + + + + Split Lines + Satırları Böl + + + + Join Lines + Satırları Birleştir + + + + Ctrl+J + Ctrl+J + + + + Move Selected Lines Up + Seçili Satırları Yukarı Taşı + + + + Ctrl+Shift+Up + Ctrl+Shift+Up + + + + Move Selected Lines Down + Seçili Satırları Aşağı Taşı + + + + Ctrl+Shift+Down + Ctrl+Shift+Down + + + + Clos&e All + Heps&ini Kapat + + + + Close All files + Tüm dosyaları kapat + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Close All Except Active Document + Aktif Belge Hariç Tümünü Kapat + + + + Close All to the Left + Soldakileri Hepsini Kapat + + + + Close All to the Right + Sağdakileri Hepsini Kapat + + + + Zoom &In + &Yakınlaştır + + + + Ctrl++ + Ctrl++ + + + + Zoom &Out + &Uzaklaştıor + + + + Ctrl+- + Ctrl+- + + + + Reset Zoom + Yakınlaştırmayı Sıfırla + + + + Ctrl+0 + Ctrl+0 + + + + About Qt + Qt Hakkında + + + + About Notepad Next + Notepad Next Hakkında + + + + Show Whitespace + Boşlukları Göster + + + + Show End of Line + Satır sonunu Göster + + + + Show All Characters + Tüm Karakterleri Göster + + + + Show Indent Guide + Girinti Kılavuzunu Göster + + + + Show Wrap Symbol + Satır Kaydırma Sembolünü Göster + + + + Word Wrap + + + + + Restore Recently Closed File + Son Kapatılan Dosyayı Geri Yükle + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + Open All Recent Files + Tüm Son Dosyaları Aç + + + + Clear Recent Files List + Son Dosyalar Listesini Temizle + + + + &Find... + &Bul... + + + + Ctrl+F + Ctrl+F + + + + Find in Files... + Dosyalarda Ara... + + + + Find &Next + &Sıradakini Bul + + + + F3 + F3 + + + + Find &Previous + &Öncekini Bul + + + + &Replace... + &Değiştir... + + + + Ctrl+H + Ctrl+H + + + + Full Screen + Tam Ekran + + + + F11 + F11 + + + + + Start Recording + Kaydetmeye Başla + + + + Playback + Oynatma + + + + Ctrl+Shift+P + Ctrl+Shift+P + + + + Save Current Recorded Macro... + Mevcut Kaydedilen Makroyu Kaydet... + + + + Run a Macro Multiple Times... + Bir Makroyu Birden Fazla Kez Çalıştır... + + + + Preferences... + Tercihler... + + + + Quick Find + Hızlıca Bul + + + + Ctrl+Alt+I + Ctrl+Alt+I + + + + Select Next Instance + Sonraki Örneği Seç + + + + Ctrl+D + Ctrl+D + + + + Move to Trash... + Çöp Kutusuna Taşı... + + + + Move to Trash + Çöp Kutusuna Taşı + + + + Check for Updates... + Güncellemeleri Kontrol Et... + + + + &Go to Line... + &Satıra Git... + + + + Ctrl+G + Ctrl+G + + + + Print... + Yazdır... + + + + Ctrl+P + Ctrl+P + + + + Open Folder as Workspace... + Klasörü Çalışma Alanı Olarak Aç... + + + + Toggle Single Line Comment + Tek Satırlı Yorumu Aç/Kapa + + + + Ctrl+/ + Ctrl+/ + + + + Single Line Comment + Tek Satır Yorumu + + + + Ctrl+K + Ctrl+K + + + + Single Line Uncomment + Tek Satır Yorumunu Kaldır + + + + Ctrl+Shift+K + Ctrl+Shift+K + + + + Edit Macros... + Makroları Düzenle... + + + + This is not currently implemented + Bu şu anda uygulanmamaktadır + + + + Column Mode... + Sütun Modu... + + + + Next Tab + + + + + Ctrl+Tab + + + + + Previous Tab + + + + + Ctrl+Shift+Tab + + + + + Fold Level 1 + + + + + Alt+1 + + + + + Fold Level 2 + + + + + Alt+2 + + + + + Fold Level 3 + + + + + Alt+3 + + + + + Fold Level 4 + + + + + Alt+4 + + + + + Unfold Level 1 + + + + + Alt+Shift+1 + + + + + Unfold Level 2 + + + + + Alt+Shift+2 + + + + + Unfold Level 3 + + + + + Alt+Shift+3 + + + + + Unfold Level 4 + + + + + Alt+Shift+4 + + + + + Fold All + + + + + Alt+0 + + + + + Unfold All + + + + + Alt+Shift+0 + + + + + Fold Level 5 + + + + + Alt+5 + + + + + Fold Level 6 + + + + + Alt+6 + + + + + Fold Level 7 + + + + + Alt+7 + + + + + Fold Level 8 + + + + + Alt+8 + + + + + Fold Level 9 + + + + + Alt+9 + + + + + Unfold Level 5 + + + + + Alt+Shift+5 + + + + + Unfold Level 6 + + + + + Alt+Shift+6 + + + + + Unfold Level 7 + + + + + Alt+Shift+7 + + + + + Unfold Level 8 + + + + + Alt+Shift+8 + + + + + Unfold Level 9 + + + + + Alt+Shift+9 + + + + Alt+C + Alt+C + + + + Export as HTML... + HTML Olarak Dışa Aktar... + + + + Export as RTF... + RTF Olarak Dışa Aktar... + + + + Copy as HTML + HTML olarak kopyala + + + + Copy as RTF + RTF olarak kopyala + + + + Base 64 Encode + Base 64 Kodla + + + + URL Encode + URL Kodla + + + + Base 64 Decode + Base 64 Çözümle + + + + URL Decode + URL Çözümle + + + + Copy URL + + + + + Remove Empty Lines + Boş Satırları Sil + + + + + Show in Explorer + Dosya Gezgininde Göster + + + + Open Command Prompt Here + Komut İstemi'ni Burada Aç + + + + Toggle Bookmark + Yer İmlerini Aç/Kapat + + + + Ctrl+F2 + Ctrl+F2 + + + + Next Bookmark + Sonraki Yer İmi + + + + F2 + F2 + + + + Previous Bookmark + Önceki Yer İmi + + + + Shift+F2 + Shift+F2 + + + + Clear Bookmarks + Yer İmlerini Temizle + + + + Invert Bookmarks + Yer İmlerini Tersine Çevir + + + + Go to line + Satıra Git + + + + Line Number (1 - %1) + Satır Numarası (1 - %1) + + + + Stop Recording + Kaydetmeyi Durdur + + + + New %1 + Yeni %1 + + + + Create File + Dosya Oluştur + + + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> mevcut değil. Oluşturmak istiyor musunuz? + + + + + Save file <b>%1</b>? + Dosyayı kaydetmek istiyor musunuz: <b>%1</b>? + + + + + Save File + Dosyayı Kaydet + + + + Open Folder as Workspace + Klasörü Çalışma Alanı Olarak Aç + + + + Reload File + Dosyayı Yeniden Yükle + + + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + <b>%1</b>'i yeniden yüklemek istediğinizden emin misiniz? Kaydedilmemiş değişiklikler kaybolacak. + + + + Save a Copy As + Bir Kopyayı Farklı Kaydet + + + + + Rename + Yeniden Adlandır + + + + Name: + İsim: + + + + Delete File + Dosyayı Sil + + + + Are you sure you want to move <b>%1</b> to the trash? + <b>%1</b>'i çöp kutusuna taşımak istediğinizden emin misiniz? + + + + Error Deleting File + Dosya Silme Hatası + + + + Something went wrong deleting <b>%1</b>? + <b>%1</b> silinirken bir hata oluştu? + + + + Administrator + + + + + Error Saving File + Dosyayı Kaydetme Hatası + + + + An error occurred when saving <b>%1</b><br><br>Error: %2 + Bir hata oluştu. <b>%1</b> kaydedilirken hata oluştu. <br><br>Hata: %2 + + + + Zoom: %1% + + + + + No updates are available at this time. + Şu anda kullanılabilir güncellemeler bulunmuyor. + + + + PreferencesDialog + + + Preferences + Tercihler + + + + Show menu bar + + + + + Show toolbar + + + + + Show status bar + + + + + Restore previous session + + + + + Temporary files + + + + + Translation: + + + + + Exit on last tab closed + + + + + Default Font + + + + + Font + + + + + Font Size + + + + + pt + + + + + TextLabel + Metin + + + + An application restart is required to apply certain settings. + + + + Menu Bar + Menü Çubuğu + + + Tool Bar + Araç Çubuğu + + + Status Bar + Durum Çubuğu + + + Restore Previous Session + Önceki Oturumu Geri Yükle + + + + Unsaved changes + Kaydedilmemiş değişiklikler + + + Temp Files + Geçici Dosyalar + + + + Combine search results + Arama sonuçlarını birleştir + + + + Warning + Uyarı + + + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + Bu özellik deneyseldir ve kritik öneme sahip işler için güvenli olduğu düşünülmemelidir. Olası veri kaybına yol açabilir. Kendi sorumluluğunuzda kullanın. + + + + <System Default> + + + + + QObject + + + List All Tabs + Tüm Sekmeleri Listele + + + + Detach Group + Grubu Ayır + + + + Minimize + + + + Close Active Tab + Aktif Sekmeyi Kapat + + + Close Group + Grubu Kapat + + + + Close Tab + Sekmeyi Kapat + + + + QuickFindWidget + + + Frame + Çerçeve + + + + Match case + Eşleşme durumu + + + + Aa + Aa + + + + Match whole word + Tüm kelimeyi eşleştir + + + + |A| + |A| + + + + Use regular expression + Regex + + + + . * + . * + + + + Alt+E + Alt+E + + + + Find... + Bul... + + + + %L1/%L2 + + + + + SearchResultsDock + + + Search Results + Arama Sonuçları + + + + Collapse All + Tümünü Daralt + + + + Expand All + Tümünü Genişlet + + + + Delete Entry + Girdiyi Sil + + + + Delete All + Hepsini Sil + + + + Updater + + + Would you like to download the update now? + Güncellemeyi şimdi indirmek ister misiniz? + + + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + Güncellemeyi şimdi indirmek ister misiniz? Bu zorunlu bir güncellemedir, şimdi çıkmak uygulamayı kapatacaktır + + + + Version %1 of %2 has been released! + %2'nin %1 sürümü yayınlandı! + + + + No updates are available for the moment + Şu an için herhangi bir güncelleme mevcut değil + + + + Congratulations! You are running the latest version of %1 + Tebrikler! %1'in en son sürümünü çalıştırıyorsunuz + + + + ads::CAutoHideTab + + + Detach + Ayır + + + + Pin To... + + + + + Top + + + + + Left + + + + + Right + + + + + Bottom + + + + + Unpin (Dock) + + + + + Close + Kapat + + + + ads::CDockAreaTitleBar + + + Detach Group + Grubu Ayır + + + + Detach + Ayır + + + + + Unpin (Dock) + + + + + + Pin Group + + + + + Pin Group To... + + + + + Top + + + + + Left + + + + + Right + + + + + Bottom + + + + + + Minimize + + + + + + + Close + Kapat + + + + + Close Group + Grubu Kapat + + + + Close Other Groups + Diğer Grupları Kapat + + + + Pin Active Tab (Press Ctrl to Pin Group) + + + + + Close Active Tab + Aktif Sekmeyi Kapat + + + + ads::CDockManager + + + Show View + Göster + + + + ads::CDockWidgetTab + + + Detach + Ayır + + + + Pin + + + + + Pin To... + + + + + Top + + + + + Left + + + + + Right + + + + + Bottom + + + + + Close + Kapat + + + + Close Others + Diğerlerini Kapat + + + diff --git a/i18n/NotepadNext_uk_UA.ts b/i18n/NotepadNext_uk_UA.ts new file mode 100644 index 000000000..0de3498c3 --- /dev/null +++ b/i18n/NotepadNext_uk_UA.ts @@ -0,0 +1,2457 @@ + + + + + ColumnEditorDialog + + + Column Mode + Створення стовпця + + + + Text + Текст + + + + Numbers + Числа + + + + Start: + Початок: + + + + Step: + Крок: + + + + DebugLogDock + + + Debug Log + + + + + Downloader + + + + Updater + Менеджер оновлень + + + + + + Downloading updates + Завантаження оновлень + + + + Time remaining: 0 minutes + Часу залишилось: 0 хвилин + + + + Open + Відкрити + + + + + Stop + Зупинити + + + + + Time remaining + Часу залишилось + + + + unknown + невідомо + + + + Error + Помилка + + + + Cannot find downloaded update! + Завантажене оновлення не знайдено! + + + + Close + Закрити + + + + Download complete! + Завантаження завершено! + + + + The installer will open separately + + + + + Click "OK" to begin installing the update + Натисніть "ОК" для встановлення оновлення + + + + In order to install the update, you may need to quit the application. + Щоб інсталювати оновлення, вам може знадобитися вийти з програми. + + + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + + + + + Click the "Open" button to apply the update + Натисніть кнопку "Відкрити" для застосування оновлень + + + + Are you sure you want to cancel the download? + Ви дійсно хочете скасувати завантаження ? + + + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + Ви дійсно хочете скасувати завантаження ? Це важливе оновлення, тому роботу програми буде завершено. + + + + + %1 bytes + %1 байт + + + + + %1 KB + %1 КБ + + + + + %1 MB + %1 МБ + + + + of + з + + + + Downloading Updates + Завантаження оновлень + + + + Time Remaining + Часу залишилось + + + + Unknown + Невідомо + + + + about %1 hours + близько %1 годин + + + + about one hour + близько години + + + + %1 minutes + %1 хвилин + + + + 1 minute + 1 хвилина + + + + %1 seconds + %1 секунд + + + + 1 second + 1 секунда + + + + EditorInfoStatusBar + + + Length: %L1 Lines: %L2 + Розмір: %L1 Рядків: %L2 + + + + Sel: N/A + Обрано: N/A + + + + Sel: %L1 | %L2 + Обрано: %L1 | %L2 + + + + Ln: %L1 Col: %L2 + Рядок: %L1 Стовпець: %L2 + + + + Macintosh (CR) + Macintosh (CR) + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + ANSI + ANSI + + + + UTF-8 + UTF-8 + + + + EditorInspectorDock + + + Editor Inspector + Аналізатор редактору + + + + Position Information + Інформація про позицію + + + + Current Position + Поточна позиція + + + + Current Position (x, y) + Поточна позиція (x, y) + + + + Column + Стовпець + + + + Current Style + Поточний стиль + + + + Current Line + Поточний рядок + + + + Line Length + Розмір рядка + + + + Line End Position + Позиція кінця рядка + + + + Line Indentation + Відступ рядка + + + + Line Indent Position + Позиція відступу рядка + + + + Selection Information + Інформація про виділення + + + + Mode + Режим + + + + Is Rectangle + Прямокутне виділення ? + + + + Selection Empty + Виділення пусте ? + + + + Main Selection + + + + + # of Selections + + + + + Multiple Selections + + + + + Document Information + Інформація про документ + + + + Length + Довжина + + + + Line Count + Кількісь рядків + + + + View Information + Інформація про видиму область + + + + Lines on Screen + Макс. кількість рядків на екрані + + + + First Visible Line + Перший видимий рядок + + + + X Offset + Зміщення по осі Х + + + + Fold Information + Інформація про блок + + + + Visible From Doc Line + + + + + Doc Line From Visible + + + + + Fold Level + Рівень блоку + + + + Is Fold Header + Початок блоку ? + + + + Fold Parent + Початок блоку + + + + Last Child + Кінець блоку + + + + Contracted Fold Next + + + + + Caret + Каретка + + + + Anchor + Якір + + + + Caret Virtual Space + + + + + Anchor Virtual Space + + + + + FileList + + + File List + Список файлів + + + + FindReplaceDialog + + + + + Find + &Шукати + + + + Search Mode + Режим пошуку + + + + &Normal + З&а замовчуванням + + + + E&xtended (\n, \r, \t, \0, \x...) + Р&озширений(\n, \r, \t, \0, \x...) + + + + Re&gular expression + Р&егулярні вирази + + + + &. matches newline + + + + + Transparenc&y + &Прозорість вікна + + + + On losing focus + При втраті фокусу + + + + Always + Завжди + + + + Coun&t + &Кількість + + + + &Replace + &Замінити + + + + Replace &All + Замінити &всі + + + + Replace All in &Opened Documents + За&мінити всі у відкритих документах + + + + Find All in All &Opened Documents + З&найти всі у всих відкритих документах + + + + Find All in Current Document + Знайти всі у поточному документі + + + + Close + Закрити + + + + &Find: + Шукати: + + + + Replace: + Замінити: + + + + Backward direction + Зворотній напрям + + + + Match &whole word only + Ш&укати ціле слово + + + + Match &case + Враховувати рег&істр + + + + Wra&p Around + &Циклічний пошук + + + + Replace + Замінити + + + Replaced %L1 matches + Замінено %L1 відповідність + + + + + Replaced %Ln matches + + + + + + + + + The end of the document has been reached. Found 1st occurrence from the top. + Досягнуто кінець документу. Знайдено 1 збіг. + + + + No matches found. + Нічого не знайдено. + + + + 1 occurrence was replaced + Був замінений 1 збіг + + + + No more occurrences were found + Більше збігів не знайдено + + + + Found %Ln matches + + Знайдено %Ln співпадінь + + + + + + Found %L1 matches + Знайдено %L1 збігів + + + + FolderAsWorkspaceDock + + + Folder as Workspace + Каталог як робочий простір + + + + HexViewerDock + + + Hex Viewer + HEX-переглядач + + + + LanguageInspectorDock + + + Language Inspector + Аналізатор синтаксису + + + + Language: + Синтаксис: + + + + Lexer: + + + + + Properties: + Властивості: + + + + Property + Властивість + + + + Type + Тип + + + + + Description + Опис + + + + Value + Значення + + + + Keywords: + Ключові слова: + + + + ID + ID + + + + Styles: + Стилі: + + + + TextLabel + + + + + Position %1 Style %2 + Позиція: %1 Стиль: %2 + + + + LuaConsoleDock + + + Lua Console + Консоль Lua + + + + MacroEditorDialog + + + Macro Editor + Редактор макросів + + + + Name + Назва + + + + Shortcut + Скорочення + + + + Steps: + Операції: + + + + Insert Macro Step + Вставити операцію + + + + Delete Selected Macro Step + Видалити операцію + + + + Move Selected Macro Step Up + Перемістити операцію вгору + + + + Move Selected Macro Step Down + Перемістити операцію вниз + + + + Copy Selected Macro + Копіювати макрос + + + + Delete Selected Macro + Видалити макрос + + + + Delete Macro + Видалити макрос + + + + Are you sure you want to delete <b>%1</b>? + Ви дійсно хочете видалити <b>%1</b>? + + + + (Copy) + (копіювати) + + + + MacroRunDialog + + + Run a Macro Multiple Times + Виконати макрос багато разів + + + + Macro: + Макрос: + + + + Run Until End of File + Виконувати до кінця файлу + + + + Execute... + Виконати... + + + + times + разів + + + + Run + Виконати + + + + Cancel + Скасувати + + + + MacroSaveDialog + + + Save Macro + Збереження макросу + + + + Name: + Назва: + + + + Shortcut: + Скорочення: + + + + OK + OK + + + + Cancel + Скасувати + + + + MacroStepTableModel + + + Name + Назва + + + + Text + Текст + + + + MainWindow + + + Notepad Next[*] + Notepad Next[*] + + + + + + + + + + &File + &Файл + + + + Close More + Закрити + + + + &Recent Files + &Останні файли + + + + + Export As + Експортувати як + + + + &Edit + &Редагування + + + + Copy More + Копіювати + + + + Indent + Відступ + + + + EOL Conversion + Перетворення символу кінця рядку (EOL) + + + + Convert Case + Змінити регістр + + + + Line Operations + Операції з рядками + + + + Comment/Uncomment + Закоментувати/розкоментувати + + + + Copy As + Копіювати як + + + + Encoding/Decoding + Зашифрувати/Розшифрувати + + + + Search + &Пошук + + + + Bookmarks + Закладки + + + + &View + &Вид + + + + &Zoom + &Масштаб + + + + Show Symbol + Показувати символи + + + + Fold Level + Згорнути рівень + + + + Unfold Level + Розгорнути рівень + + + + Language + &Синтаксис + + + + Settings + П&араметри + + + + Macro + &Макрос + + + + Help + &Довідка + + + + Encoding + Набір символів + + + + Main Tool Bar + Головна панель інструментів + + + + &New + &Новий + + + + Create a new file + Створити новий файл + + + + Ctrl+N + + + + + &Open... + &Відкрити... + + + + Ctrl+O + + + + + &Save + &Зберегти + + + + Save + Зберегти + + + + Ctrl+S + + + + + E&xit + Ви&йти + + + + &Undo + &Відмінити операцію + + + + Ctrl+Z + + + + + &Redo + &Повторити операцію + + + + Ctrl+Y + + + + + Cu&t + В&ирізати + + + + Ctrl+X + + + + + &Copy + &Копіювати + + + + Ctrl+C + + + + + &Paste + В&ставити + + + + Ctrl+V + + + + + &Delete + Ви&далити + + + + Del + + + + + Copy Full Path + Копіювати повний шлях + + + + Copy File Name + Копіювати назву файлу + + + + Copy File Directory + Копіювати назву каталогу + + + + &Close + За&крити + + + + Close the current file + Закрити поточний файл + + + + Ctrl+W + + + + + Save &As... + З&берегти як... + + + + Ctrl+Alt+S + + + + + Save a Copy As... + Зберегти копію як... + + + + Sav&e All + Зб&ерегти все + + + + Ctrl+Shift+S + + + + + Select A&ll + &Обрати всі + + + + Ctrl+A + + + + + Increase Indent + Збільшити відступ + + + + Decrease Indent + Зменшити відступ + + + + Rename... + Перейменувати... + + + + Re&load + &Перезавантажити + + + + Windows (CR LF) + Windows (CR LF) + + + + Unix (LF) + Unix (LF) + + + + Macintosh (CR) + Macintosh (CR) + + + + UPPER CASE + ВЕРХНІЙ РЕГІСТР + + + + Convert text to upper case + Перетворити в ВЕРХНІЙ РЕГІСТР + + + + lower case + нижній регістр + + + + Convert text to lower case + Перетворити в нижній регістр + + + + Duplicate Current Line + Дублювати поточний рядок + + + + Alt+Down + + + + + Split Lines + Розділити рядки + + + + Join Lines + Об'єднати рядки + + + + Ctrl+J + + + + + Move Selected Lines Up + Перемістити поточний рядок вверх + + + + Ctrl+Shift+Up + + + + + Move Selected Lines Down + Перемістити поточний рядок вниз + + + + Ctrl+Shift+Down + + + + + Clos&e All + Зак&рити все + + + + Close All files + Закрити всі файли + + + + Ctrl+Shift+W + + + + + Close All Except Active Document + Закрити всі документи окрім поточного + + + + Close All to the Left + Закрити всі ліворуч + + + + Close All to the Right + Закрити всі праворуч + + + + Zoom &In + Ма&сштаб + + + + + Ctrl++ + + + + + Zoom &Out + &Масштаб - + + + + Ctrl+- + + + + + Reset Zoom + Масштаб за змовчуванням + + + + Ctrl+0 + + + + + About Qt + Про Qt + + + + About Notepad Next + Про Notepad Next + + + + Show Whitespace + Показувати пробіл + + + + Show End of Line + Показувати кінець рядку + + + + Show All Characters + Показувати всі символи + + + + Show Indent Guide + Показувати лінії відступу + + + + Show Wrap Symbol + Показувати символ переносу + + + + Word Wrap + Перенесення слів + + + + Restore Recently Closed File + Відновити щойно закритий файл + + + + Ctrl+Shift+T + + + + + Open All Recent Files + Відкрити ві нещодавні файли + + + + Clear Recent Files List + Очистити список нещодавніх файлів + + + + &Find... + &Знайти... + + + + Ctrl+F + + + + + Find in Files... + Знайти в файлах... + + + + Find &Next + Знайти &наступний + + + + F3 + + + + + Find &Previous + Знайти &попередній + + + + &Replace... + З&амінити... + + + + Ctrl+H + + + + + Full Screen + Повноекранний режим + + + + F11 + + + + + + Start Recording + Почати запис + + + + Playback + Виконати + + + + Ctrl+Shift+P + + + + + Save Current Recorded Macro... + Зберегти щойно записаний макрос... + + + + Run a Macro Multiple Times... + Виконати макрос багато разів... + + + + Preferences... + Налаштування... + + + + Quick Find + Швидкий пошук + + + + Ctrl+Alt+I + + + + + Select Next Instance + Виділити схожі вирази + + + + Ctrl+D + + + + + Move to Trash... + Перемістити до смітника... + + + + Move to Trash + Перемістити до смітника + + + + Check for Updates... + Перевірити оновлення... + + + + &Go to Line... + П&ерейти до рядку... + + + + Ctrl+G + + + + + Print... + Друк... + + + + Ctrl+P + + + + + Open Folder as Workspace... + Відкрити каталог як робочий простір... + + + + Toggle Single Line Comment + Однорядковий коментар + + + + Ctrl+/ + + + + + Single Line Comment + Закоментувати один рядок + + + + Ctrl+K + + + + + Single Line Uncomment + Розкоментувати один рядок + + + + Ctrl+Shift+K + + + + + Edit Macros... + Редагувати макрос... + + + + This is not currently implemented + Ця можливість ще не реалізована + + + + Column Mode... + Створити стовпець... + + + + Export as HTML... + Експортувати як HTML... + + + + Export as RTF... + Експортувати як RTF... + + + + Copy as HTML + Копіювати як HTML + + + + Copy as RTF + Копіювати як RTF + + + + Base 64 Encode + Зашифрувати Base 64 + + + + URL Encode + Зашифрувати URL + + + + Base 64 Decode + Розшифрувати Base 64 + + + + URL Decode + Розшифрувати URL + + + + Copy URL + Копіювати URL + + + + Remove Empty Lines + Видалити пусті рядки + + + + + Show in Explorer + Показати в файловому менеджері + + + + Open Command Prompt Here + Відкрити командний рядок тут + + + + Toggle Bookmark + Додати/видалити закладку + + + + Ctrl+F2 + + + + + Next Bookmark + Наступна закладка + + + + F2 + + + + + Previous Bookmark + Попередня закладка + + + + Shift+F2 + + + + + Clear Bookmarks + Очистити закладки + + + + Invert Bookmarks + Інвертувати закладки + + + + Next Tab + Наступна вкладка + + + + Ctrl+Tab + + + + + Previous Tab + Попередня вкладка + + + + Ctrl+Shift+Tab + + + + + Fold Level 1 + Згорнути рівень 1 + + + + Alt+1 + + + + + Fold Level 2 + Згорнути рівень 2 + + + + Alt+2 + + + + + Fold Level 3 + Згорнути рівень 3 + + + + Alt+3 + + + + + Fold Level 4 + Згорнути рівень 4 + + + + Alt+4 + + + + + Unfold Level 1 + Розгорнути рівень 1 + + + + Alt+Shift+1 + + + + + Unfold Level 2 + Розгорнути рівень 2 + + + + Alt+Shift+2 + + + + + Unfold Level 3 + Розгорнути рівень 3 + + + + Alt+Shift+3 + + + + + Unfold Level 4 + Розгорнути рівень 4 + + + + Alt+Shift+4 + + + + + Fold All + Згорнути всі + + + + Alt+0 + + + + + Unfold All + Розгорнути всі + + + + Alt+Shift+0 + + + + + Fold Level 5 + Згорнути рівень 5 + + + + Alt+5 + + + + + Fold Level 6 + Згорнути рівень 6 + + + + Alt+6 + + + + + Fold Level 7 + Згорнути рівень 7 + + + + Alt+7 + + + + + Fold Level 8 + Згорнути рівень 8 + + + + Alt+8 + + + + + Fold Level 9 + Згорнути рівень 9 + + + + Alt+9 + + + + + Unfold Level 5 + Розгорнути рівень 5 + + + + Alt+Shift+5 + + + + + Unfold Level 6 + Розгорнути рівень 6 + + + + Alt+Shift+6 + + + + + Unfold Level 7 + Розгорнути рівень 7 + + + + Alt+Shift+7 + + + + + Unfold Level 8 + Розгорнути рівень 8 + + + + Alt+Shift+8 + + + + + Unfold Level 9 + Розгорнути рівень 9 + + + + Alt+Shift+9 + + + + + Go to line + Перейти до рядку + + + + Line Number (1 - %1) + Номер рядку (1 - %1) + + + + Stop Recording + Зупинити запис + + + + New %1 + Новий %1 + + + + Create File + Створити файл + + + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> не існує. Бажаєте створити його ? + + + + + Save file <b>%1</b>? + Зберегти файл <b>%1</b>? + + + + + Save File + Зберегти файл + + + + Open Folder as Workspace + Відкрити каталог як робочий простір + + + + Reload File + Перезавантажити файл + + + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + Ви дійсно хочете перезавантажити файл<b>%1</b>? Всі не збережені зміни будут втрачені. + + + + Save a Copy As + Зберегти копію як + + + + + Rename + Перейменувати + + + + Name: + Назва: + + + + Delete File + Видалити файл + + + + Are you sure you want to move <b>%1</b> to the trash? + Ви дійсно хочете перемістити файл <b>%1</b> до смітника ? + + + + Error Deleting File + Помилка видалення файлу + + + + Something went wrong deleting <b>%1</b>? + Під час видалення щось пішло не так <b>%1</b>? + + + + Administrator + Адміністратор + + + + Error Saving File + Помилка збереження файлу + + + + An error occurred when saving <b>%1</b><br><br>Error: %2 + Під час збереження виникла помилка<b>%1</b><br><br>Помилка: %2 + + + + Zoom: %1% + Масштаб: %1% + + + + No updates are available at this time. + На даний момент не має ніяких оновлень. + + + + PreferencesDialog + + + Preferences + Налаштування + + + + Show menu bar + Показувати панель меню + + + + Show toolbar + Показувати панель інструментів + + + + Show status bar + Показувати рядок стану + + + + Restore previous session + Відновлювати попередній сеанс + + + + Temporary files + Тимчасові файли + + + + Translation: + Локалізація: + + + + Exit on last tab closed + Закривати програму при закритті останньої вкладки + + + + Default Font + Шрифт за замовчуванням + + + + Font + Шрифт + + + + Font Size + Розмір + + + + pt + + + + + TextLabel + Текстове поле + + + + An application restart is required to apply certain settings. + Для застосування деяких змін потрібно перезапустити програму. + + + Menu Bar + Панель меню + + + Tool Bar + Панель інструментів + + + Status Bar + Панель стану + + + Restore Previous Session + Відновлювати попередню сесію + + + + Unsaved changes + Не збережені зміни + + + Temp Files + Тимчасові файли + + + + Combine search results + Об'єднувати результати пошуку + + + + Warning + Попередження + + + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + Ця функція є експериментальною, тому її не можна вважати безпечною. Її використання може призвести до втрати даних. Використовуйте цю опцію на власний розсуд. + + + + <System Default> + <Мова системи> + + + + QObject + + + List All Tabs + Список всіх вкладок + + + + Detach Group + Відокремити групу + + + + Minimize + Мінімізувати + + + Close Active Tab + Закрити поточну вкладку + + + Close Group + Закрити групу + + + + Close Tab + Закрити вкладку + + + + QuickFindWidget + + + Frame + + + + + Match case + Чутливість до регістру + + + + Aa + Aa + + + + Match whole word + Шукати ціле слово + + + + |A| + |A| + + + + Use regular expression + Використовувати регулярний вираз + + + + . * + . * + + + + Alt+E + Alt+E + + + + Find... + Шукати... + + + + %L1/%L2 + %L1/%L2 + + + + SearchResultsDock + + + Search Results + Результати пошуку + + + + Collapse All + Згорнути все + + + + Expand All + Розгорнути все + + + + Delete Entry + Видалити запис + + + + Delete All + Видалити все + + + + Updater + + + Would you like to download the update now? + Ви бажаєте завантажити оновлення зараз ? + + + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + Ви бажаєте завантажити оновлення зараз ? Це важливе оновлення, тому роботу програми буде завершено. + + + + Version %1 of %2 has been released! + Версія %1 з %2 була опублікована! + + + + No updates are available for the moment + На даний момент жодні оновлення не доступні + + + + Congratulations! You are running the latest version of %1 + Вітаємо! Ви використовуєте останню версію %1 + + + + ads::CAutoHideTab + + + Detach + Відокремити + + + + Pin To... + Прикріпити до... + + + + Top + Верх + + + + Left + Ліворуч + + + + Right + Праворуч + + + + Bottom + Низ + + + + Unpin (Dock) + + + + + Close + Закрити + + + + ads::CDockAreaTitleBar + + + Detach Group + Відокремити групу + + + + Detach + Відокремити + + + + + Unpin (Dock) + + + + + + Pin Group + Прикріпити групу + + + + Pin Group To... + + + + + Top + Верх + + + + Left + Ліворуч + + + + Right + Праворуч + + + + Bottom + Низ + + + + + Minimize + Мінімізувати + + + + + + Close + Закрити + + + + + Close Group + Закрити групу + + + + Close Other Groups + Закрити інші групи + + + + Pin Active Tab (Press Ctrl to Pin Group) + + + + + Close Active Tab + Закрити поточну вкладку + + + + ads::CDockManager + + + Show View + + + + + ads::CDockWidgetTab + + + Detach + Відокремити + + + + Pin + + + + + Pin To... + + + + + Top + + + + + Left + + + + + Right + + + + + Bottom + + + + + Close + Закрити + + + + Close Others + + + + diff --git a/i18n/NotepadNext_zh_CN.ts b/i18n/NotepadNext_zh_CN.ts index 0efc3c69a..96dac0d7e 100644 --- a/i18n/NotepadNext_zh_CN.ts +++ b/i18n/NotepadNext_zh_CN.ts @@ -1,2325 +1,2485 @@ - - + + ColumnEditorDialog - - Column Mode - 列编辑模式 + + Column Mode + 列编辑模式 - - Text - 文本 + + Text + 文本 - - Numbers - 数字 + + Numbers + 数字 - - Start: - 开始: + + Start: + 开始: - - Step: - 步长: + + Step: + 步长: - - + + DebugLogDock - - Debug Log - 调试日志 + + Debug Log + 调试日志 - - - EditorInfoStatusBar + + + Downloader - - Length: %L1 Lines: %L2 - 长度:%L1 行数:%L2 + + + Updater + 更新器 - - Sel: N/A - 选择:N/A + + + + Downloading updates + 正在下载更新 - - Sel: %L1 | %L2 - 选择:%L1 | %L2 + + Time remaining: 0 minutes + 剩余时间:0 分钟 - - Ln: %L1 Col: %L2 - 行:%L1 列:%L2 + + Open + 开始 - - Macintosh (CR) - + + + Stop + 停止 - - Windows (CR LF) - + + + Time remaining + 剩余时间 - - Unix (LF) - + + unknown + 未知 - - ANSI - + + Error + 错误 - - UTF-8 - + + Cannot find downloaded update! + 无法找到可下载更新! - - UTF-8 BOM - + + Close + 关闭 - - UTF-16LE BOM - + + Download complete! + 下载完成! - - UTF-16BE BOM - + + The installer will open separately + 安装程序会在单独的窗口打开 - - OVR - This is a short abbreviation to indicate characters will be replaced when typing - + + Click "OK" to begin installing the update + 点击“OK”按钮开始安装更新 - - INS - This is a short abbreviation to indicate characters will be inserted when typing - + + In order to install the update, you may need to quit the application. + 为了安装更新,你可能需要退出已打开的程序。 - - - EditorInspectorDock - - Editor Inspector - 编辑查看器 + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + 为了安装更新,你可能需要退出已打开的程序。这是一个强制更新,现在退出将关闭应用程序 - - Position Information - 位置信息 + + Click the "Open" button to apply the update + 点击“Open”按钮开始应用更新 - - Current Position - 当前位置 + + Are you sure you want to cancel the download? + 你确定要取消下载吗? - - Current Position (x, y) - 当前位置 (x, y) + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + 你确定要取消下载吗?这是一个强制更新,现在退出将关闭应用程序 - - Column - + + + %1 bytes + %1 字节 - - Current Style - 当前样式 + + + %1 KB + - - Current Line - 当前行 + + + %1 MB + - - Line Length - 行长 + + of + / - - Line End Position - 行尾位置 + + Downloading Updates + 下载更新中 - - Line Indentation - 行缩进 + + Time Remaining + 剩余时间 - - Line Indent Position - 行缩进位置 + + Unknown + 未知 - - Selection Information - 选择信息 + + about %1 hours + 约 %1 小时 - - Mode - 模式 + + about one hour + 约 1 小时 - - Is Rectangle - 矩形选择 + + %1 minutes + %1 分钟 - - Selection Empty - 已选择空 + + 1 minute + 1 分钟 - - Main Selection - 主光标编号 + + %1 seconds + %1 秒 - - # of Selections - 光标数 + + 1 second + 1 秒 + + + EditorInfoStatusBar - - Multiple Selections - 光标列表 + + Sel: N/A + 选择:N/A - - Document Information - 文档信息 + + Length: %L1 Lines: %L2 + 长度:%L1 行数:%L2 - - Length - 长度 + + Sel: %L1 | %L2 + 选择:%L1 | %L2 - - Line Count - 行数 + + Ln: %L1 Col: %L2 + 行:%L1 列:%L2 - - View Information - 视图信息 + + Macintosh (CR) + - - Lines on Screen - 屏幕上行数 + + Windows (CR LF) + - - First Visible Line - 第一可视行 + + Unix (LF) + - - X Offset - X 偏移 + + ANSI + - - Fold Information - 折叠信息 + + UTF-8 + + + + EditorInspectorDock - - Visible From Doc Line - 从文档行可见 + + Editor Inspector + 编辑查看器 - - Doc Line From Visible - 可见文档行 + + Current Position + 当前位置 - - Fold Level - 折叠层级 + + Current Position (x, y) + 当前位置 (x, y) - - Is Fold Header - 是折叠组标题行 + + Column + - - Fold Parent - 折叠组父级 + + Current Style + 当前样式 - - Last Child - 最后子节点 + + Current Line + 当前行 - - Contracted Fold Next - 下一个已折叠项 + + Line Length + 行长 - - Caret - 光标位置 + + Line End Position + 行尾位置 - - Anchor - 锚点位置 + + Line Indentation + 行缩进 - - Caret Virtual Space - 插入虚拟空格 + + Line Indent Position + 行缩进位置 - - Anchor Virtual Space - 定位虚拟空格 + + Selection Information + 选择信息 - - - FileList - - File List - 文件列表 + + Is Rectangle + 仅多光标模式下为 True + 矩形选择 - - ... - + + Selection Empty + 已选择空 - - Sort by File Name - + + Main Selection + 永远是最后一个光标;编号从 #0 开始;光标列表见下方(Multiple Selections) + 主光标编号 - - - FindReplaceDialog - - - - Find - 查找 + + # of Selections + 光标数 - - Search Mode - 搜索模式 + + Multiple Selections + 光标列表 - - &Normal - 正常模式(&N) + + Document Information + 文档信息 - - E&xtended (\n, \r, \t, \0, \x...) - 扩展模式(&E) (\n, \r, \t, \0, \x...) + + Position Information + 位置信息 - - Re&gular expression - 正则表达式 (&g) + + Mode + 模式 - - &. matches newline - &. 匹配换行 + + Length + 长度 - - Transparenc&y - 透明度(&y) + + Line Count + 行数 - - On losing focus - 失去焦点时 + + View Information + 指主编辑器视图 + 视图信息 - - Always - 总是 + + Lines on Screen + 屏幕上行数 - - Coun&t - 计数(&t) + + First Visible Line + 第一可视行 - - &Replace - 替换(&R) + + X Offset + TODO:具体含义尚不清楚 + X 偏移 - - Replace &All - 全部替换(&A) + + Fold Information + 折叠信息 - - Replace All in &Opened Documents - 替换所有打开文件(&O) + + Visible From Doc Line + TODO:具体含义尚不清楚 + 从文档行可见 - - Find All in All &Opened Documents - 查找所有打开文件(&O) + + Doc Line From Visible + TODO:具体含义尚不清楚 + 可见文档行 - - Find All in Current Document - 查找当前文档 + + Fold Level + 折叠层级 - - Close - 关闭 + + Is Fold Header + 是折叠组标题行 - - &Find: - &查找: + + Fold Parent + (行号) + 折叠组父级 - - Replace: - 替换: + + Last Child + (行号) + 最后子节点 - - Backward direction - 反向搜索 + + Contracted Fold Next + (行号) + 下一个已折叠项 - - Match &whole word only - 全词匹配(&w) + + Caret + 选择终止的位置 + 光标位置 - - Match &case - 匹配大小写(&c) + + Anchor + 选择开始的位置 + 锚点位置 - - Wra&p Around - 循环搜索(&p) + + Caret Virtual Space + TODO:具体含义尚不清楚 + 插入虚拟空格 - - Replace - 替换 + + Anchor Virtual Space + TODO:具体含义尚不清楚 + 定位虚拟空格 - - - - Replaced %Ln matches - - 已替换 %Ln 个匹配项 - + + + FileList + + + File List + 文件列表 + + + + FindReplaceDialog + + + + + Find + 查找 + + + + Search Mode + 搜索模式 + + + + &Normal + 正常模式(&N) + + + + E&xtended (\n, \r, \t, \0, \x...) + 扩展模式(&E) (\n, \r, \t, \0, \x...) + + + + Re&gular expression + 正则表达式 (&g) + + + + &. matches newline + &. 匹配换行 + + + + Transparenc&y + 透明度(&y) + + + + On losing focus + 失去焦点时 + + + + Always + 总是 + + + + Coun&t + 计数(&t) + + + + &Replace + 替换(&R) + + + + Replace &All + 全部替换(&A) + + + + Replace All in &Opened Documents + 替换所有打开文件(&O) + + + + Find All in All &Opened Documents + 查找所有打开文件(&O) - - The end of the document has been reached. Found 1st occurrence from the top. - 已经到达文档的末尾。从顶部找到第一个匹配项。 + + Find All in Current Document + 查找当前文档 - - No matches found. - 没有找到匹配项。 + + Close + 关闭 - - 1 occurrence was replaced - 已替换 1 个匹配项 + + &Find: + &查找: - - No more occurrences were found - 没有找到更多匹配项 + + Replace: + 替换: + + + + Backward direction + 反向搜索 + + + + Match &whole word only + 全词匹配(&w) + + + + Match &case + 匹配大小写(&c) + + + + Wra&p Around + 开启此选项,搜索达到文件末尾后,会自动从头继续搜索。 + 循环搜索(&p) + + + + Replace + 替换 + + + Replaced %L1 matches + 已替换 %L1 个匹配项 - - Found %Ln matches - - 找到 %Ln 个匹配项 - - - - - FolderAsWorkspaceDock + + + Replaced %Ln matches + + 已替换 %Ln 个匹配项 + + - - Folder as Workspace - 文件夹工作区 + + The end of the document has been reached. Found 1st occurrence from the top. + 已经到达文档的末尾。从顶部找到第一个匹配项。 - - - LanguageInspectorDock - - Language Inspector - 语言查看器 + + No matches found. + 没有找到匹配项。 - - Language: - 语言: + + 1 occurrence was replaced + 已替换 1 个匹配项 - - Lexer: - 词法分析器: + + No more occurrences were found + 没有找到更多匹配项 + + + + Found %Ln matches + + 找到 %Ln 个匹配项 + - - Properties: - 属性: + Found %L1 matches + 查找了 %L1 个匹配项 + + + FolderAsWorkspaceDock - - Property - 属性 + + Folder as Workspace + 窗口标题 + 文件夹工作区 + + + HexViewerDock - - Type - 类型 + + Hex Viewer + Hex 查看器 + + + LanguageInspectorDock - - - Description - 描述 + + Language Inspector + 语言查看器 - - Value - + + Language: + 语言: - - Keywords: - 关键词: + + Lexer: + 词法分析器: - - ID - + + Properties: + 属性: - - Styles: - 样式: + + Property + 属性 - - TextLabel - 文本标签 + + Type + 类型 - - Position %1 Style %2 - 位置 %1 样式 %2 + + + Description + 描述 - - - LuaConsoleDock - - Lua Console - Lua 终端 + + Value + - - - MacroEditorDialog - - Macro Editor - 宏编辑器 + + Keywords: + 关键词: - - Name - 名称 + + ID + - - Shortcut - 快捷方式 + + Styles: + 样式: - - Steps: - 步骤: + + TextLabel + 文本标签 - - Insert Macro Step - 插入宏步 + + Position %1 Style %2 + 位置 %1 样式 %2 + + + LuaConsoleDock - - Delete Selected Macro Step - 删除已选宏步 + + Lua Console + Lua 终端 + + + MacroEditorDialog - - Move Selected Macro Step Up - 向上移动已选宏步 + + Macro Editor + 宏编辑器 - - Move Selected Macro Step Down - 向下移动已选宏步 + + Name + 名称 - - Copy Selected Macro - 复制已选宏步 + + Shortcut + 快捷方式 - - Delete Selected Macro - 清空已选宏 + + Steps: + 步骤: - - Delete Macro - 删除宏 + + Insert Macro Step + 插入宏步 - - Are you sure you want to delete <b>%1</b>? - 你确定想要删掉<b>%1</b>吗? + + Delete Selected Macro Step + 删除已选宏步 - - (Copy) - (复制) + + Move Selected Macro Step Up + 向上移动已选宏步 - - - MacroRunDialog - - Run a Macro Multiple Times - 多次运行宏 + + Move Selected Macro Step Down + 向下移动已选宏步 - - Macro: - 宏: + + Copy Selected Macro + 复制已选宏步 - - Run Until End of File - 运行至文件末尾 + + Delete Selected Macro + 清空已选宏 - - Execute... - 执行... + + Delete Macro + 删除宏 - - times - + + Are you sure you want to delete <b>%1</b>? + 你确定想要删掉<b>%1</b>吗? - - Run - 运行 + + (Copy) + (复制) + + + MacroRunDialog - - Cancel - 取消 + + Run a Macro Multiple Times + 多次运行宏 - - - MacroSaveDialog - - Save Macro - 保存宏 + + Macro: + 宏: - - Name: - 宏名: + + Run Until End of File + 运行至文件末尾 - - Shortcut: - 快捷键: + + Execute... + 执行... - - OK - 确定 + + times + - - Cancel - 取消 + + Run + 运行 - - - MacroStepTableModel - - Name - 名称 + + Cancel + 取消 + + + MacroSaveDialog - - Text - 文本 + + Save Macro + 保存宏 - - - MainWindow - - Notepad Next[*] - + + Name: + 宏名: - - + - + + Shortcut: + 快捷键: - - &File - 文件(&F) + + OK + 确定 - - Close More - 更多关闭方式 + + Cancel + 取消 + + + MacroStepTableModel - - &Recent Files - 最近打开的文件(&R) + + Name + 名称 - - - Export As - 导出为 + + Text + 文本 + + + MainWindow - - &Edit - 编辑(&E) + + Notepad Next[*] + 【不译】 + - - Copy More - 更多复制方式 + + + + 【不译】按F11进入全屏模式,右上角按钮。用于退出全屏 + - - Indent - 缩进 + + &File + 文件(&F) - - EOL Conversion - 行尾序列(EOL)转换 + + Close More + 更多关闭方式 - - Convert Case - 大小写转换 + + &Recent Files + 最近打开的文件(&R) - - Line Operations - 行操作 + + &Edit + 编辑(&E) - - Comment/Uncomment - 注释/取消注释 + + Copy More + 更多复制方式 - - Copy As - 复制为 + + Indent + 缩进 - - Encoding/Decoding - 编码/解码 + + EOL Conversion + 行尾序列(EOL)转换 - - Search - 搜索 + + Convert Case + 大小写转换 - - Bookmarks - 书签 + + Line Operations + 行操作 - - Mark All Occurrences - + + Comment/Uncomment + 注释/取消注释 - - Clear Marks - + + Search + 搜索 - - &View - 视图(&V) + + Bookmarks + 书签 - - &Zoom - 缩放(&Z) + + &View + 视图(&V) - - Show Symbol - 显示符号标记 + + &Zoom + 缩放(&Z) - - Fold Level - 折叠层级 + + Show Symbol + 显示符号标记 - - Unfold Level - + + Fold Level + 折叠层级 - - Language - 语言 + + Unfold Level + - - Settings - 选项 + + Language + 语言 - - Macro - + + Settings + 选项 - - Help - 帮助 + + Macro + - - Encoding - 编码 + + Help + 帮助 - - Main Tool Bar - 主工具栏 + + Encoding + 编码 - - &New - 新建(&N) + + Main Tool Bar + 主工具栏 - - Create a new file - 新建文件 + + &New + 新建(&N) - - Ctrl+N - + + Create a new file + 新建文件 - - &Open... - 打开(&O)... + + Ctrl+N + - - Ctrl+O - + + &Open... + 打开(&O)... - - &Save - 保存(&S) + + Ctrl+O + - - Save - 保存 + + &Save + 保存(&S) - - Ctrl+S - + + Save + 保存 - - E&xit - 退出(&E) + + Ctrl+S + - - &Undo - 撤销(&U) + + E&xit + 退出(&E) - - Ctrl+Z - + + &Undo + 撤销(&U) - - &Redo - 重做(&R) + + Ctrl+Z + - - Ctrl+Y - + + &Redo + 重做(&R) - - Cu&t - 剪切(&t) + + Ctrl+Y + - - Ctrl+X - + + Cu&t + 剪切(&t) - - &Copy - 复制(&C) + + Ctrl+X + - - Ctrl+C - + + &Copy + 复制(&C) - - &Paste - 粘贴(&P) + + Ctrl+C + - - Ctrl+V - + + &Paste + 粘贴(&P) - - &Delete - 删除(&D) + + Ctrl+V + - - Del - + + &Delete + 删除(&D) - - Copy Full Path - 复制完整路径 + + Del + Delete 对应的快捷键 + - - Copy File Name - 复制文件名 + + Copy Full Path + 复制完整路径 - - Copy File Directory - 复制文件夹路径 + + Copy File Name + 复制文件名 - - &Close - 关闭(&C) + + Copy File Directory + 复制文件夹路径 - - Close the current file - 关闭当前文件 + + &Close + 关闭(&C) - - Ctrl+W - + + Close the current file + 关闭当前文件 - - Save &As... - 另存为(&A)... + + Ctrl+W + - - Ctrl+Alt+S - + + Save &As... + 另存为(&A)... - - Save a Copy As... - 副本另存为... + + Ctrl+Alt+S + - - Sav&e All - 保存所有(&e) + + Save a Copy As... + 副本另存为... - - Ctrl+Shift+S - + + Sav&e All + 保存所有(&e) - - Select A&ll - 选择所有(&A) + + Ctrl+Shift+S + - - Ctrl+A - + + Select A&ll + 选择所有(&A) - - Increase Indent - 增加缩进 + + Ctrl+A + - - Decrease Indent - 减少缩进 + + Increase Indent + 增加缩进 - - Rename... - 重命名... + + Decrease Indent + 减少缩进 - - Re&load - 重新加载(&l) + + Rename... + 重命名... - - Windows (CR LF) - Windows (CR LF) + + Re&load + 重新加载(&l) - - Unix (LF) - Unix (LF) + + Windows (CR LF) + Windows (CR LF) - - Macintosh (CR) - Macintosh (CR) + + Unix (LF) + Unix (LF) - - UPPER CASE - 转换为大写 + + Macintosh (CR) + Macintosh (CR) - - Convert text to upper case - 转换文本到大写 + + UPPER CASE + 仅转换选中的词。 + 转换为大写 - - lower case - 转换为小写 + + Convert text to upper case + 转换文本到大写 - - Convert text to lower case - 转换文本到小写 + + lower case + 仅转换选中的词。 + 转换为小写 - - Duplicate Current Line - 复制并插入当前行 + + Convert text to lower case + 转换文本到小写 - - Alt+Down - + + Duplicate Current Line + 会在下一行插入 + 复制并插入当前行 - - Split Lines - 拆分当前行 + + Alt+Down + - - Join Lines - 合并多行 + + Split Lines + 效果与打开“自动折行”一致,不过使用了硬换行 + 拆分当前行 - - Ctrl+J - + + Join Lines + 需要选中多行,否则没有效果。 + 合并多行 - - Move Selected Lines Up - 向下移动选中的行 + + Ctrl+J + - - Ctrl+Shift+Up - + + Move Selected Lines Up + 向下移动选中的行 - - Move Selected Lines Down - 向上移动选中的行 + + Ctrl+Shift+Up + - - Ctrl+Shift+Down - + + Move Selected Lines Down + 向上移动选中的行 - - Clos&e All - 关闭所有(&e) + + Ctrl+Shift+Down + - - Close All files - 关闭所有文件 + + Clos&e All + 关闭所有(&e) - - Ctrl+Shift+W - + + Close All files + 关闭所有文件 - - Close All Except Active Document - 关闭其他 + + Ctrl+Shift+W + - - Close All to the Left - 关闭至左侧 + + Close All Except Active Document + 关闭其他 - - Close All to the Right - 关闭至右侧 + + Close All to the Left + 关闭至左侧 - - Zoom &In - 放大(&I) + + Close All to the Right + 关闭至右侧 - - Ctrl++ - + + Zoom &In + 放大(&I) - - Zoom &Out - 缩小(&O) + + Ctrl++ + - - Ctrl+- - + + Zoom &Out + 缩小(&O) - - Reset Zoom - 重置缩放 + + Ctrl+- + - - Ctrl+0 - + + Reset Zoom + 重置缩放 - - About Qt - 关于 Qt + + Ctrl+0 + - - About Notepad Next - 关于 Notepad Next + + Toggle Single Line Comment + 切换单行注释 - - Show Whitespace - 显示空格 + + Ctrl+/ + - - Show End of Line - 显示行尾 + + Single Line Comment + 单行注释 - - Show All Characters - 显示所有字符 + + Ctrl+K + - - Show Indent Guide - 显示缩进指引 + + Single Line Uncomment + 取消单行注释 - - Show Wrap Symbol - 显示换行标记 + + Ctrl+Shift+K + - - Word Wrap - 自动换行 + + Edit Macros... + 编辑宏... - - Restore Recently Closed File - 恢复最近关闭的文件 + + This is not currently implemented + 此功能尚未实现 - - Ctrl+Shift+T - + + Column Mode... + 列编辑模式... - - Open All Recent Files - 打开所有最近关闭的文件 + + Export as HTML... + 导出为 HTML... - - Clear Recent Files List - 清除最近打开的文件 + + Export as RTF... + 导出为 RTF... - - &Find... - 查找(&F)... + + Copy as HTML + 复制为 HTML - - Ctrl+F - + + Copy as RTF + 复制为 RTF - - Find in Files... - 在文件中查找... + + Base 64 Encode + Base 64 编码 - - Find &Next - 查找下一个(&N) + + URL Encode + URL 编码 - - F3 - + + Base 64 Decode + Base 64 解码 - - Find &Previous - 查找上一个(&P) + + URL Decode + URL 解码 - - Shift+F3 - + + Copy URL + 复制 URL - - &Replace... - 替换(&R)... + + Remove Empty Lines + 删除空行 - - Ctrl+H - + + + Show in Explorer + 在资源管理器中查看 - - Full Screen - 全屏 + + Open Command Prompt Here + 在此打开命令提示符 - - F11 - + + Toggle Bookmark + 切换书签 - - - Start Recording - 开始录制 + + Ctrl+F2 + - - Playback - 重放宏 + + Next Bookmark + 下一个书签 - - Ctrl+Shift+P - + + F2 + - - Save Current Recorded Macro... - 保存当前已录制的宏... + + Previous Bookmark + 上一个书签 - - Run a Macro Multiple Times... - 多次运行宏... + + Shift+F2 + - - Preferences... - 偏好设置.... + + Clear Bookmarks + 清除书签 - - Quick Find - 快速查找 + + Invert Bookmarks + 书签顺序上下颠倒 + 反转书签 - - Ctrl+Alt+I - + + Next Tab + - - Select Next Instance - 选择下一个实例 + + Ctrl+Tab + - - Ctrl+D - + + Previous Tab + - - Move to Trash... - 移动至回收站... + + Ctrl+Shift+Tab + - - Move to Trash - 移动至回收站 + + Fold Level 1 + - - Check for Updates... - 检查更新... + + Alt+1 + - - &Go to Line... - 转跳到行(&G)... + + Fold Level 2 + - - Ctrl+G - + + Alt+2 + - - Print... - 打印... + + Fold Level 3 + - - Ctrl+P - + + Alt+3 + - - Open Folder as Workspace... - 打开文件夹为工作区... + + Fold Level 4 + - - Toggle Single Line Comment - 切换单行注释 + + Alt+4 + - - Ctrl+/ - + + Unfold Level 1 + - - Single Line Comment - 单行注释 + + Alt+Shift+1 + - - Ctrl+K - + + Unfold Level 2 + - - Single Line Uncomment - 取消单行注释 + + Alt+Shift+2 + - - Ctrl+Shift+K - + + Unfold Level 3 + - - Edit Macros... - 编辑宏... + + Alt+Shift+3 + - - This is not currently implemented - 此功能尚未实现 + + Unfold Level 4 + - - Column Mode... - 列编辑模式... + + Alt+Shift+4 + - - Export as HTML... - 导出为 HTML... + + Fold All + - - Export as RTF... - 导出为 RTF... + + Alt+0 + - - Copy as HTML - 复制为 HTML + + Unfold All + - - Copy as RTF - 复制为 RTF + + Alt+Shift+0 + - - Base 64 Encode - Base 64 编码 + + Fold Level 5 + - - URL Encode - URL 编码 + + Alt+5 + - - Base 64 Decode - Base 64 解码 + + Fold Level 6 + - - URL Decode - URL 解码 + + Alt+6 + - - Copy URL - 复制 URL + + Fold Level 7 + - - Remove Empty Lines - 删除空行 + + Alt+7 + - - - Show in Explorer - 在资源管理器中查看 + + Fold Level 8 + - - Open %1 Here - + + Alt+8 + - - Toggle Bookmark - 切换书签 + + Fold Level 9 + - - Ctrl+F2 - + + Alt+9 + - - Next Bookmark - 下一个书签 + + Unfold Level 5 + - - F2 - + + Alt+Shift+5 + - - Previous Bookmark - 上一个书签 + + Unfold Level 6 + - - Shift+F2 - + + Alt+Shift+6 + - - Clear Bookmarks - 清除书签 + + Unfold Level 7 + - - Invert Bookmarks - 反转书签 + + Alt+Shift+7 + - - Next Tab - + + Unfold Level 8 + - - Ctrl+Tab - + + Alt+Shift+8 + - - Previous Tab - + + Unfold Level 9 + - - Ctrl+Shift+Tab - + + Alt+Shift+9 + - - Fold Level 1 - + + About Qt + 关于 Qt - - Alt+1 - + + + Export As + 导出为 - - Fold Level 2 - + + Copy As + 复制为 - - Alt+2 - + + Encoding/Decoding + 编码/解码 - - Fold Level 3 - + + About Notepad Next + 关于 Notepad Next - - Alt+3 - + + Show Whitespace + 显示空格 - - Fold Level 4 - + + Show End of Line + 显示行尾 - - Alt+4 - + + Show All Characters + 显示所有字符 - - Unfold Level 1 - + + Show Indent Guide + 显示缩进指引 - - Alt+Shift+1 - + + Show Wrap Symbol + 显示换行标记 - - Unfold Level 2 - + + Word Wrap + 自动换行 - - Alt+Shift+2 - + + Restore Recently Closed File + 只恢复(重新打开)一个文件 + 恢复最近关闭的文件 - - Unfold Level 3 - + + Ctrl+Shift+T + - - Alt+Shift+3 - + + Open All Recent Files + 历史记录里有的文件都会打开 + 打开所有最近关闭的文件 - - Unfold Level 4 - + + Clear Recent Files List + 清除最近打开的文件 - - Alt+Shift+4 - + + &Find... + 查找(&F)... - - Fold All - + + Ctrl+F + - - Alt+0 - + + Find in Files... + 在文件中查找... - - Unfold All - + + Find &Next + 查找下一个(&N) - - Alt+Shift+0 - + + F3 + - - Fold Level 5 - + + Find &Previous + 查找上一个(&P) - - Alt+5 - + + &Replace... + 替换(&R)... - - Fold Level 6 - + + Ctrl+H + - - Alt+6 - + + Full Screen + 全屏 - - Fold Level 7 - + + F11 + - - Alt+7 - + + + Start Recording + 开始录制 - - Fold Level 8 - + + Playback + "Macro > Playback" + 重放宏 - - Alt+8 - + + Ctrl+Shift+P + - - Fold Level 9 - + + Save Current Recorded Macro... + 保存当前已录制的宏... - - Alt+9 - + + Run a Macro Multiple Times... + 多次运行宏... - - Unfold Level 5 - + + Preferences... + 偏好设置.... - - Alt+Shift+5 - + + Quick Find + 快速查找 - - Unfold Level 6 - + + Ctrl+Alt+I + - - Alt+Shift+6 - + + Select Next Instance + 选择下一个实例 - - Unfold Level 7 - + + Ctrl+D + - - Alt+Shift+7 - + + Move to Trash... + 移动至回收站... - - Unfold Level 8 - + + Move to Trash + 移动至回收站 - - Alt+Shift+8 - + + Check for Updates... + 检查更新... - - Unfold Level 9 - + + &Go to Line... + 转跳到行(&G)... - - Alt+Shift+9 - + + Ctrl+G + - - - Toggle Overtype - + + Print... + 打印... - - Ins - + + Ctrl+P + - - Debug Info... - + + Open Folder as Workspace... + 打开文件夹为工作区... - - Cut Bookmarked Lines - + + Go to line + 转跳到行 - - Copy Bookmarked Lines - + + Line Number (1 - %1) + 行号(1 - %1) - - Delete Bookmarked Lines - + + Stop Recording + 停止录制 - - Mark Style 1 - + + New %1 + 用作新建空白文件的标题 + 新文件 %1 - - Mark Style 2 - + + Create File + 新建文件 - - Clear Style 1 - + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> 尚不存在,你想要新建一个吗? - - Clear Style 2 - + + + Save file <b>%1</b>? + 保存文件 <b>%1</b>? - - Mark Style 3 - + + + Save File + 保存文件 - - Clear Style 3 - + + Open Folder as Workspace + 打开文件夹作为工作区 - - - Clear All Styles - + + Reload File + 重新加载文件 - - Remove Duplicate Lines - + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + 你确定要重新加载 <b>%1</b>?任何未保存的修改都会丢失。 - - Remove Consecutive Duplicate Lines - + + Administrator + - - Sort Lines Ascending - + + Error Saving File + 保存文件时出错 - - Sort Lines Descending - + + Save a Copy As + 副本另存为 - - Sort Lines Ascending (Case-Insensitive) - + + + Rename + 重命名 - - Sort Lines Descending (Case-Insensitive) - + + Name: + 宏名: - - Sort Lines by Length Ascending - + + Delete File + 删除文件 - - Sort Lines by Length Descending - + + Are you sure you want to move <b>%1</b> to the trash? + 你确定要将 <b>%1</b> 移至回收站? - - Reverse Line Order - + + Error Deleting File + 删除文件时出错 - - Go to line - 转跳到行 + + Something went wrong deleting <b>%1</b>? + 删除 <b>%1</b> 时出错了? - - Line Number (1 - %1) - 行号(1 - %1) + + An error occurred when saving <b>%1</b><br><br>Error: %2 + 保存 <b>%1</b> 时发生了错误<br><br>错误:%2 - - Stop Recording - 停止录制 + + Zoom: %1% + - - Debug Info - + + No updates are available at this time. + 本次无可用更新。 + + + PreferencesDialog - - New %1 - 新文件 %1 + + Preferences + 偏好设置 - - Create File - 新建文件 + + Show menu bar + - - <b>%1</b> does not exist. Do you want to create it? - <b>%1</b> 尚不存在,你想要新建一个吗? + + Show toolbar + - - - Save file <b>%1</b>? - 保存文件 <b>%1</b>? + + Show status bar + - - - Save File - 保存文件 + + Restore previous session + - - Open Folder as Workspace - 打开文件夹作为工作区 + + Temporary files + - - - Reload File - 重新加载文件 + + Translation: + - - Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. - 你确定要重新加载 <b>%1</b>?任何未保存的修改都会丢失。 + + Exit on last tab closed + - - Save a Copy As - 副本另存为 + + Default Font + - - - Rename - 重命名 + + Font + - - Name: - 宏名: + + Font Size + - - Delete File - 删除文件 + + pt + - - Are you sure you want to move <b>%1</b> to the trash? - 你确定要将 <b>%1</b> 移至回收站? + + TextLabel + 文本标签 - - Error Deleting File - 删除文件时出错 + + An application restart is required to apply certain settings. + - - Something went wrong deleting <b>%1</b>? - 删除 <b>%1</b> 时出错了? + Menu Bar + 菜单栏 - - Administrator - + Tool Bar + 工具栏 - - <b>%1</b> has been modified by another program. Do you want to reload it? - + Status Bar + 状态栏 - - Read error - + Restore Previous Session + 还原之前的会话 - - Write error - + + Unsaved changes + 未保存的更改 - - Fatal error - + Temp Files + 临时文件们 - - Resource error - + + Combine search results + 结合搜索结果 - - Open error - + + Warning + 警告 - - Abort error - + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + 本功能是实验性的。对于关键性的重要工作开启本功能并不安全,可能导致数据丢失,使用时风险自负。 - - Timeout error - + + <System Default> + + + + QObject - - Unspecified error - + + List All Tabs + 列出所有标签页 - - Remove error - + + Detach Group + 脱离分组 - - Rename error - + + Minimize + - - Position error - + Close Active Tab + 关闭活动的标签页 - - Resize error - + Close Group + 关闭分组 - - Permissions error - + + Close Tab + 关闭标签页 + + + QuickFindWidget - - Copy error - + + Frame + 嵌入式搜索窗口,标题不会显示。 + - - Unknown error (%1) - + + Match case + 区分大小写 - - Error Saving File - 保存文件时出错 + + Aa + “区分大小写”按钮 + - - An error occurred when saving <b>%1</b><br><br>Error: %2 - 保存 <b>%1</b> 时发生了错误<br><br>错误:%2 + + Match whole word + 全词匹配 - - Zoom: %1% - + + |A| + “全词匹配”按钮 + - - No updates are available at this time. - 本次无可用更新。 + + Use regular expression + 使用正则表达式 - - - PreferencesDialog - - Preferences - 偏好设置 + + . * + “正则表达式”按钮 + - - Show menu bar - + + Alt+E + - - Show toolbar - + + Find... + 查找... - - Show status bar - + + %L1/%L2 + + + + SearchResultsDock - - Restore previous session - + + Search Results + 搜索结果 - - Unsaved changes - 未保存的更改 + + Collapse All + 全部折叠 - - Temporary files - + + Expand All + 全部展开 - - Recenter find/replace dialog when opened - + + Delete Entry + 删除条目 - - Combine search results - 结合搜索结果 + + Delete All + 删除所有 + + + Updater - - Translation: - + + Would you like to download the update now? + 你想要现在下载更新吗? - - Exit on last tab closed - + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + 你想要现在下载更新吗?这是一个强制性的更新,现在退出将关闭应用程序 - - Default Font - + + Version %1 of %2 has been released! + %1 版本的 %2 已经发布了! - - Font - + + No updates are available for the moment + 暂时没有可用的更新 - - Font Size - + + Congratulations! You are running the latest version of %1 + 恭喜!你已经在使用最新版本的 %1 + + + ads::CAutoHideTab - - pt - + + Detach + 脱离 - - Default Line Endings - + + Pin To... + - - Highlight URLs - + + Top + - - Show Line Numbers - + + Left + - - - Default Directory - + + Right + - - Follow Current Document - + + Bottom + - - Last Used Directory - + + Unpin (Dock) + - - ... - + + Close + 关闭 + + + ads::CDockAreaTitleBar - - TextLabel - 文本标签 + + Detach Group + 脱离分组 - - An application restart is required to apply certain settings. - + + Detach + 脱离 - - Warning - 警告 + + + Unpin (Dock) + - - This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. - 本功能是实验性的。对于关键性的重要工作开启本功能并不安全,可能导致数据丢失,使用时风险自负。 + + + Pin Group + - - System Default - + + Pin Group To... + - - Windows (CR LF) - Windows (CR LF) + + Top + - - Linux (LF) - + + Left + - - Macintosh (CR) - Macintosh (CR) + + Right + - - <System Default> - + + Bottom + - - - QuickFindWidget - - Frame - + + + Minimize + - - Find... - 查找... + + + + Close + 关闭 - - Match case - 区分大小写 + + + Close Group + 关闭分组 - - Aa - + + Close Other Groups + 关闭其他分组 - - Match whole word - 全词匹配 + + Pin Active Tab (Press Ctrl to Pin Group) + - - |A| - + + Close Active Tab + 关闭活动的标签页 + + + ads::CDockManager - - Use regular expression - 使用正则表达式 + + Show View + 显示视图 + + + ads::CDockWidgetTab - - . * - + + Detach + 脱离 - - Alt+E - + + Pin + - - %L1/%L2 - + + Pin To... + - - - SearchResultsDock - - Search Results - 搜索结果 + + Top + - - Copy Results to Clipboard - + + Left + - - Collapse All - 全部折叠 + + Right + - - Expand All - 全部展开 + + Bottom + - - Delete Entry - 删除条目 + + Close + 关闭 - - Delete All - 删除所有 + + Close Others + 关闭其他 - + diff --git a/i18n/NotepadNext_zh_TW.ts b/i18n/NotepadNext_zh_TW.ts index df244d331..2dbb35a66 100644 --- a/i18n/NotepadNext_zh_TW.ts +++ b/i18n/NotepadNext_zh_TW.ts @@ -1,2325 +1,2449 @@ - - + + ColumnEditorDialog - - Column Mode - 欄編輯模式 + + Column Mode + 欄編輯模式 - - Text - 文字 + + Text + 文字 - - Numbers - 數字 + + Numbers + 數字 - - Start: - 開始: + + Start: + 開始: - - Step: - 步驟: + + Step: + 步驟: - - + + DebugLogDock - - Debug Log - 除錯日誌 + + Debug Log + 除錯日誌 - - - EditorInfoStatusBar + + + Downloader - - Length: %L1 Lines: %L2 - 長度:%L1 行數:%L2 + + + Updater + 更新程式 - - Sel: N/A - 選擇:N/A + + + + Downloading updates + 正在下載更新 - - Sel: %L1 | %L2 - 選擇:%L1 | %L2 + + Time remaining: 0 minutes + 剩餘時間:0 分鐘 - - Ln: %L1 Col: %L2 - 行:%L1 列:%L2 + + Open + 開啟 - - Macintosh (CR) - Macintosh (CR) + + + Stop + 停止 - - Windows (CR LF) - Windows (CR LF) + + + Time remaining + 剩餘時間 - - Unix (LF) - Unix (LF) + + unknown + 未知 - - ANSI - ANSI + + Error + 錯誤 - - UTF-8 - UTF-8 + + Cannot find downloaded update! + 找不到已下載的更新! - - UTF-8 BOM - UTF-8 BOM + + Close + 關閉 - - UTF-16LE BOM - UTF-16LE BOM + + Download complete! + 下載完成! - - UTF-16BE BOM - UTF-16BE BOM + + The installer will open separately + 安裝程式將單獨開啟 - - OVR - This is a short abbreviation to indicate characters will be replaced when typing - OVR + + Click "OK" to begin installing the update + 點選「確定」開始安裝更新 - - INS - This is a short abbreviation to indicate characters will be inserted when typing - INS + + In order to install the update, you may need to quit the application. + 為了安裝更新,您可能需要退出應用程式。 - - - EditorInspectorDock - - Editor Inspector - 編輯器檢視器 + + In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application + 為了安裝更新,您可能需要退出應用程式。這是一個強制更新,現在退出將關閉應用程式 - - Position Information - 位置資訊 + + Click the "Open" button to apply the update + 點選「開啟」按鈕以應用更新 - - Current Position - 目前位置 + + Are you sure you want to cancel the download? + 您確定要取消下載嗎? - - Current Position (x, y) - 目前位置 (x, y) + + Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application + 您確定要取消下載嗎?這是一個強制更新,現在退出將關閉應用程式 - - Column - + + + %1 bytes + %1 位元組 - - Current Style - 目前樣式 + + + %1 KB + %1 KB - - Current Line - 目前這行 + + + %1 MB + %1 MB - - Line Length - 行長 + + of + / - - Line End Position - 行尾位置 + + Downloading Updates + 正在下載更新 - - Line Indentation - 行縮排 + + Time Remaining + 剩餘時間 - - Line Indent Position - 行縮排位置 + + Unknown + 未知 - - Selection Information - 選取資訊 + + about %1 hours + 大約 %1 小時 - - Mode - 模式 + + about one hour + 大約一小時 - - Is Rectangle - 是否為矩形 + + %1 minutes + %1 分鐘 - - Selection Empty - 選取是否為空 + + 1 minute + 1 分鐘 - - Main Selection - 主要選取 + + %1 seconds + %1 秒 - - # of Selections - 選取數量 + + 1 second + 1 秒 + + + EditorInfoStatusBar - - Multiple Selections - 多重選取 + + Sel: N/A + 選擇:N/A - - Document Information - 文件資訊 + + Length: %L1 Lines: %L2 + 長度:%L1 行數:%L2 - - Length - 長度 + + Sel: %L1 | %L2 + 選擇:%L1 | %L2 - - Line Count - 行數 + + Ln: %L1 Col: %L2 + 行:%L1 列:%L2 - - View Information - 檢視資訊 + + Macintosh (CR) + Macintosh (CR) - - Lines on Screen - 螢幕上的行數 + + Windows (CR LF) + Windows (CR LF) - - First Visible Line - 第一可見行 + + Unix (LF) + Unix (LF) - - X Offset - X 偏移 + + ANSI + ANSI - - Fold Information - 折疊資訊 + + UTF-8 + UTF-8 + + + EditorInspectorDock - - Visible From Doc Line - 從文件行可見 + + Editor Inspector + 編輯器檢視器 - - Doc Line From Visible - 可見文件行 + + Current Position + 目前位置 - - Fold Level - 折疊層級 + + Current Position (x, y) + 目前位置 (x, y) - - Is Fold Header - 是否為折疊標頭 + + Column + - - Fold Parent - 折疊父項 + + Current Style + 目前樣式 - - Last Child - 最後子項 + + Current Line + 目前這行 - - Contracted Fold Next - 下一個已折疊項 + + Line Length + 行長 - - Caret - 游標位置 + + Line End Position + 行尾位置 - - Anchor - 錨點位置 + + Line Indentation + 行縮排 - - Caret Virtual Space - 插入虛擬空格 + + Line Indent Position + 行縮排位置 - - Anchor Virtual Space - 定位虛擬空格 + + Selection Information + 選取資訊 - - - FileList - - File List - 檔案列表 + + Is Rectangle + 是否為矩形 - - ... - ... + + Selection Empty + 選取是否為空 - - Sort by File Name - Sort by File Name + + Main Selection + 主要選取 - - - FindReplaceDialog - - - - Find - 查詢 + + # of Selections + 選取數量 - - Search Mode - 搜尋模式 + + Multiple Selections + 多重選取 - - &Normal - 正常模式(&N) + + Document Information + 文件資訊 - - E&xtended (\n, \r, \t, \0, \x...) - 擴充套件模式(&E) (\n, \r, \t, \0, \x...) + + Position Information + 位置資訊 - - Re&gular expression - 正則表達式 (&g) + + Mode + 模式 - - &. matches newline - &. 符合換行符號 + + Length + 長度 - - Transparenc&y - 透明度(&y) + + Line Count + 行數 - - On losing focus - 失去焦點時 + + View Information + 檢視資訊 - - Always - 總是 + + Lines on Screen + 螢幕上的行數 - - Coun&t - 計數(&t) + + First Visible Line + 第一可見行 - - &Replace - 取代(&R) + + X Offset + X 偏移 - - Replace &All - 全部取代(&A) + + Fold Information + 折疊資訊 - - Replace All in &Opened Documents - 取代所有開啟檔案(&O) + + Visible From Doc Line + 從文件行可見 - - Find All in All &Opened Documents - 查詢所有開啟檔案(&O) + + Doc Line From Visible + 可見文件行 - - Find All in Current Document - 查詢目前文件 + + Fold Level + 折疊層級 - - Close - 關閉 + + Is Fold Header + 是否為折疊標頭 - - &Find: - &查詢: + + Fold Parent + 折疊父項 - - Replace: - 取代: + + Last Child + 最後子項 - - Backward direction - 反向搜尋 + + Contracted Fold Next + 下一個已折疊項 - - Match &whole word only - 全詞符合(&w) + + Caret + 游標位置 - - Match &case - 大小寫相符(&c) + + Anchor + 錨點位置 - - Wra&p Around - 迴圈搜尋(&p) + + Caret Virtual Space + 插入虛擬空格 - - Replace - 取代 + + Anchor Virtual Space + 定位虛擬空格 - - - - Replaced %Ln matches - - 已取代 %Ln 個符合項目 - + + + FileList + + + File List + 檔案列表 + + + + FindReplaceDialog + + + + + Find + 查詢 + + + + Search Mode + 搜尋模式 + + + + &Normal + 正常模式(&N) + + + + E&xtended (\n, \r, \t, \0, \x...) + 擴充套件模式(&E) (\n, \r, \t, \0, \x...) + + + + Re&gular expression + 正則表達式 (&g) + + + + &. matches newline + &. 符合換行符號 + + + + Transparenc&y + 透明度(&y) + + + + On losing focus + 失去焦點時 + + + + Always + 總是 + + + + Coun&t + 計數(&t) + + + + &Replace + 取代(&R) + + + + Replace &All + 全部取代(&A) + + + + Replace All in &Opened Documents + 取代所有開啟檔案(&O) - - The end of the document has been reached. Found 1st occurrence from the top. - 已經到達文件的末尾。從頂端找到第一個符合項目。 + + Find All in All &Opened Documents + 查詢所有開啟檔案(&O) - - No matches found. - 沒有找到符合項目。 + + Find All in Current Document + 查詢目前文件 - - 1 occurrence was replaced - 已取代 1 個符合項目 + + Close + 關閉 - - No more occurrences were found - 沒有找到更多符合項目 + + &Find: + &查詢: + + + + Replace: + 取代: + + + + Backward direction + 反向搜尋 + + + + Match &whole word only + 全詞符合(&w) + + + + Match &case + 大小寫相符(&c) + + + + Wra&p Around + 迴圈搜尋(&p) + + + + Replace + 取代 - - Found %Ln matches - - 找到 %Ln 個符合項目 - - - - - FolderAsWorkspaceDock + + + Replaced %Ln matches + + 已取代 %Ln 個符合項目 + + - - Folder as Workspace - 資料夾作為工作區 + + The end of the document has been reached. Found 1st occurrence from the top. + 已經到達文件的末尾。從頂部找到第一個符合項目。 - - - LanguageInspectorDock - - Language Inspector - 語言檢視器 + + No matches found. + 沒有找到符合項目。 - - Language: - 語言: + + 1 occurrence was replaced + 已取代 1 個符合項目 - - Lexer: - 詞法分析器: + + No more occurrences were found + 沒有找到更多符合項目 + + + Found %Ln matches + + 找到 %Ln 個符合項目 + + + + + FolderAsWorkspaceDock - - Properties: - 屬性: + + Folder as Workspace + 資料夾作為工作區 + + + HexViewerDock - - Property - 屬性 + + Hex Viewer + Hex 檢視器 + + + LanguageInspectorDock - - Type - 類型 + + Language Inspector + 語言檢視器 - - - Description - 描述 + + Language: + 語言: - - Value - + + Lexer: + 詞法分析器: - - Keywords: - 關鍵詞: + + Properties: + 屬性: - - ID - ID + + Property + 屬性 - - Styles: - 樣式: + + Type + 類型 - - TextLabel - 文字標籤 + + + Description + 描述 - - Position %1 Style %2 - 位置 %1 樣式 %2 + + Value + - - - LuaConsoleDock - - Lua Console - Lua 控制台 + + Keywords: + 關鍵詞: - - - MacroEditorDialog - - Macro Editor - 巨集編輯器 + + ID + ID - - Name - 名稱 + + Styles: + 樣式: - - Shortcut - 快捷鍵 + + TextLabel + 文字標籤 - - Steps: - 步驟: + + Position %1 Style %2 + 位置 %1 樣式 %2 + + + LuaConsoleDock - - Insert Macro Step - 插入巨集步驟 + + Lua Console + Lua 控制台 + + + MacroEditorDialog - - Delete Selected Macro Step - 刪除選取的巨集步驟 + + Macro Editor + 巨集編輯器 - - Move Selected Macro Step Up - 向上移動選取的巨集步驟 + + Name + 名稱 - - Move Selected Macro Step Down - 向下移動選取的巨集步驟 + + Shortcut + 快捷鍵 - - Copy Selected Macro - 複製選取的巨集 + + Steps: + 步驟: - - Delete Selected Macro - 刪除選取的巨集 + + Insert Macro Step + 插入巨集步驟 - - Delete Macro - 刪除巨集 + + Delete Selected Macro Step + 刪除選取的巨集步驟 - - Are you sure you want to delete <b>%1</b>? - 您確定要刪除 <b>%1</b> 嗎? + + Move Selected Macro Step Up + 向上移動選取的巨集步驟 - - (Copy) - (複製) + + Move Selected Macro Step Down + 向下移動選取的巨集步驟 - - - MacroRunDialog - - Run a Macro Multiple Times - 多次執行巨集 + + Copy Selected Macro + 複製選取的巨集 - - Macro: - 巨集: + + Delete Selected Macro + 刪除選取的巨集 - - Run Until End of File - 執行至檔案結尾 + + Delete Macro + 刪除巨集 - - Execute... - 執行... + + Are you sure you want to delete <b>%1</b>? + 您確定要刪除 <b>%1</b> 嗎? - - times - + + (Copy) + (複製) + + + MacroRunDialog - - Run - 執行 + + Run a Macro Multiple Times + 多次執行巨集 - - Cancel - 取消 + + Macro: + 巨集: - - - MacroSaveDialog - - Save Macro - 儲存巨集 + + Run Until End of File + 執行至檔案結尾 - - Name: - 名稱: + + Execute... + 執行... - - Shortcut: - 快捷鍵: + + times + - - OK - 確定 + + Run + 執行 - - Cancel - 取消 + + Cancel + 取消 - - - MacroStepTableModel + + + MacroSaveDialog - - Name - 名稱 + + Save Macro + 儲存巨集 - - Text - 文字 + + Name: + 名稱: - - - MainWindow - - Notepad Next[*] - Notepad Next[*] + + Shortcut: + 快捷鍵: - - + - + + + OK + 確定 - - &File - 檔案(&F) + + Cancel + 取消 + + + MacroStepTableModel - - Close More - 關閉更多 + + Name + 名稱 - - &Recent Files - 最近開啟的檔案(&R) + + Text + 文字 + + + MainWindow - - - Export As - 匯出為 + + Notepad Next[*] + Notepad Next[*] - - &Edit - 編輯(&E) + + + + + - - Copy More - 更多複製方式 + + &File + 檔案(&F) - - Indent - 縮排 + + Close More + 關閉更多 - - EOL Conversion - 行尾序列(EOL)轉換 + + &Recent Files + 最近開啟的檔案(&R) - - Convert Case - 大小寫轉換 + + &Edit + 編輯(&E) - - Line Operations - 行操作 + + Copy More + 更多複製方式 - - Comment/Uncomment - 註解/取消註解 + + Indent + 縮排 - - Copy As - 複製為 + + EOL Conversion + 行尾序列(EOL)轉換 - - Encoding/Decoding - 編碼/解碼 + + Convert Case + 大小寫轉換 - - Search - 搜尋 + + Line Operations + 行操作 - - Bookmarks - 書籤 + + Comment/Uncomment + 註解/取消註解 - - Mark All Occurrences - Mark All Occurrences + + Search + 搜尋 - - Clear Marks - Clear Marks + + Bookmarks + 書籤 - - &View - 檢視(&V) + + &View + 檢視(&V) - - &Zoom - 縮放(&Z) + + &Zoom + 縮放(&Z) - - Show Symbol - 顯示符號標記 + + Show Symbol + 顯示符號標記 - - Fold Level - 折疊層級 + + Fold Level + 折疊層級 - - Unfold Level - 展開層級 + + Unfold Level + - - Language - 語言 + + Language + 語言 - - Settings - 設定 + + Settings + 設定 - - Macro - 巨集 + + Macro + 巨集 - - Help - 幫助 + + Help + 幫助 - - Encoding - 編碼 + + Encoding + 編碼 - - Main Tool Bar - 主工具列 + + Main Tool Bar + 主工具列 - - &New - 新建(&N) + + &New + 新建(&N) - - Create a new file - 建立新檔案 + + Create a new file + 建立新檔案 - - Ctrl+N - Ctrl+N + + Ctrl+N + Ctrl+N - - &Open... - 開啟(&O)... + + &Open... + 開啟(&O)... - - Ctrl+O - Ctrl+O + + Ctrl+O + Ctrl+O - - &Save - 儲存(&S) + + &Save + 儲存(&S) - - Save - 儲存 + + Save + 儲存 - - Ctrl+S - Ctrl+S + + Ctrl+S + Ctrl+S - - E&xit - 離開(&E) + + E&xit + 離開(&E) - - &Undo - 復原(&U) + + &Undo + 復原(&U) - - Ctrl+Z - Ctrl+Z + + Ctrl+Z + Ctrl+Z - - &Redo - 重做(&R) + + &Redo + 重做(&R) - - Ctrl+Y - Ctrl+Y + + Ctrl+Y + Ctrl+Y - - Cu&t - 剪下(&t) + + Cu&t + 剪下(&t) - - Ctrl+X - Ctrl+X + + Ctrl+X + Ctrl+X - - &Copy - 複製(&C) + + &Copy + 複製(&C) - - Ctrl+C - Ctrl+C + + Ctrl+C + Ctrl+C - - &Paste - 貼上(&P) + + &Paste + 貼上(&P) - - Ctrl+V - Ctrl+V + + Ctrl+V + Ctrl+V - - &Delete - 刪除(&D) + + &Delete + 刪除(&D) - - Del - Del + + Del + Del - - Copy Full Path - 複製完整路徑 + + Copy Full Path + 複製完整路徑 - - Copy File Name - 複製檔名 + + Copy File Name + 複製檔名 - - Copy File Directory - 複製資料夾路徑 + + Copy File Directory + 複製資料夾路徑 - - &Close - 關閉(&C) + + &Close + 關閉(&C) - - Close the current file - 關閉目前檔案 + + Close the current file + 關閉目前檔案 - - Ctrl+W - Ctrl+W + + Ctrl+W + Ctrl+W - - Save &As... - 另存新檔(&A)... + + Save &As... + 另存新檔(&A)... - - Ctrl+Alt+S - Ctrl+Alt+S + + Ctrl+Alt+S + Ctrl+Alt+S - - Save a Copy As... - 另存副本為... + + Save a Copy As... + 另存副本為... - - Sav&e All - 全部儲存(&e) + + Sav&e All + 全部儲存(&e) - - Ctrl+Shift+S - Ctrl+Shift+S + + Ctrl+Shift+S + Ctrl+Shift+S - - Select A&ll - 全選(&A) + + Select A&ll + 全選(&A) - - Ctrl+A - Ctrl+A + + Ctrl+A + Ctrl+A - - Increase Indent - 增加縮排 + + Increase Indent + 增加縮排 - - Decrease Indent - 減少縮排 + + Decrease Indent + 減少縮排 - - Rename... - 重新命名... + + Rename... + 重新命名... - - Re&load - 重新載入(&l) + + Re&load + 重新載入(&l) - - Windows (CR LF) - Windows (CR LF) + + Windows (CR LF) + Windows (CR LF) - - Unix (LF) - Unix (LF) + + Unix (LF) + Unix (LF) - - Macintosh (CR) - Macintosh (CR) + + Macintosh (CR) + Macintosh (CR) - - UPPER CASE - 轉換為大寫 + + UPPER CASE + 轉換為大寫 - - Convert text to upper case - 轉換文字為大寫 + + Convert text to upper case + 轉換文字為大寫 - - lower case - 轉換為小寫 + + lower case + 轉換為小寫 - - Convert text to lower case - 轉換文字為小寫 + + Convert text to lower case + 轉換文字為小寫 - - Duplicate Current Line - 複製並插入目前這行 + + Duplicate Current Line + 複製並插入目前這行 - - Alt+Down - Alt+Down + + Alt+Down + Alt+Down - - Split Lines - 分行處理 + + Split Lines + 分行處理 - - Join Lines - 合併多行 + + Join Lines + 合併多行 - - Ctrl+J - Ctrl+J + + Ctrl+J + Ctrl+J - - Move Selected Lines Up - 向下移動選中的行 + + Move Selected Lines Up + 向下移動選中的行 - - Ctrl+Shift+Up - Ctrl+Shift+Up + + Ctrl+Shift+Up + Ctrl+Shift+Up - - Move Selected Lines Down - 向上移動選中的行 + + Move Selected Lines Down + 向上移動選中的行 - - Ctrl+Shift+Down - Ctrl+Shift+Down + + Ctrl+Shift+Down + Ctrl+Shift+Down - - Clos&e All - 關閉所有(&e) + + Clos&e All + 關閉所有(&e) - - Close All files - 關閉所有檔案 + + Close All files + 關閉所有檔案 - - Ctrl+Shift+W - Ctrl+Shift+W + + Ctrl+Shift+W + Ctrl+Shift+W - - Close All Except Active Document - 關閉其他 + + Close All Except Active Document + 關閉其他 - - Close All to the Left - 關閉至左側 + + Close All to the Left + 關閉至左側 - - Close All to the Right - 關閉至右側 + + Close All to the Right + 關閉至右側 - - Zoom &In - 放大(&I) + + Zoom &In + 放大(&I) - - Ctrl++ - Ctrl++ + + Ctrl++ + Ctrl++ - - Zoom &Out - 縮小(&O) + + Zoom &Out + 縮小(&O) - - Ctrl+- - Ctrl+- + + Ctrl+- + Ctrl+- - - Reset Zoom - 重置縮放 + + Reset Zoom + 重置縮放 - - Ctrl+0 - Ctrl+0 + + Ctrl+0 + Ctrl+0 - - About Qt - 關於 Qt + + Toggle Single Line Comment + 切換單行註解 - - About Notepad Next - 關於 Notepad Next + + Ctrl+/ + Ctrl+/ - - Show Whitespace - 顯示空格 + + Single Line Comment + 單行註解 - - Show End of Line - 顯示行尾 + + Ctrl+K + Ctrl+K - - Show All Characters - 顯示所有字元 + + Single Line Uncomment + 取消單行註解 - - Show Indent Guide - 顯示縮排指引 + + Ctrl+Shift+K + Ctrl+Shift+K - - Show Wrap Symbol - 顯示換行符號 + + Edit Macros... + 編輯巨集... - - Word Wrap - 自動換行 + + This is not currently implemented + 此功能尚未實現 - - Restore Recently Closed File - 恢復最近關閉的檔案 + + Column Mode... + 列編輯模式... - - Ctrl+Shift+T - Ctrl+Shift+T + + Next Tab + - - Open All Recent Files - 開啟所有最近的檔案 + + Ctrl+Tab + - - Clear Recent Files List - 清除最近開啟的檔案清單 + + Previous Tab + - - &Find... - 尋找(&F)... + + Ctrl+Shift+Tab + - - Ctrl+F - Ctrl+F + + Fold Level 1 + - - Find in Files... - 在檔案中尋找... + + Alt+1 + - - Find &Next - 尋找下一個(&N) + + Fold Level 2 + - - F3 - F3 + + Alt+2 + - - Find &Previous - 尋找上一個(&P) + + Fold Level 3 + - - Shift+F3 - + + Alt+3 + - - &Replace... - 取代(&R)... + + Fold Level 4 + - - Ctrl+H - Ctrl+H + + Alt+4 + - - Full Screen - 全螢幕 + + Unfold Level 1 + - - F11 - F11 + + Alt+Shift+1 + - - - Start Recording - 開始錄製 + + Unfold Level 2 + - - Playback - 播放 + + Alt+Shift+2 + - - Ctrl+Shift+P - Ctrl+Shift+P + + Unfold Level 3 + - - Save Current Recorded Macro... - 儲存目前錄製的巨集... + + Alt+Shift+3 + - - Run a Macro Multiple Times... - 多次執行巨集... + + Unfold Level 4 + - - Preferences... - 偏好設定... + + Alt+Shift+4 + - - Quick Find - 快速尋找 + + Fold All + - - Ctrl+Alt+I - Ctrl+Alt+I + + Alt+0 + - - Select Next Instance - 選擇下一個實例 + + Unfold All + - - Ctrl+D - Ctrl+D + + Alt+Shift+0 + - - Move to Trash... - 移至垃圾桶... + + Fold Level 5 + - - Move to Trash - 移至垃圾桶 + + Alt+5 + - - Check for Updates... - 檢查更新... + + Fold Level 6 + - - &Go to Line... - 跳轉到行(&G)... + + Alt+6 + - - Ctrl+G - Ctrl+G + + Fold Level 7 + - - Print... - 列印... + + Alt+7 + - - Ctrl+P - Ctrl+P + + Fold Level 8 + - - Open Folder as Workspace... - 以工作區方式開啟資料夾... + + Alt+8 + - - Toggle Single Line Comment - 切換單行註解 + + Fold Level 9 + - - Ctrl+/ - Ctrl+/ + + Alt+9 + - - Single Line Comment - 單行註解 + + Unfold Level 5 + - - Ctrl+K - Ctrl+K + + Alt+Shift+5 + - - Single Line Uncomment - 取消單行註解 + + Unfold Level 6 + - - Ctrl+Shift+K - Ctrl+Shift+K + + Alt+Shift+6 + - - Edit Macros... - 編輯巨集... + + Unfold Level 7 + - - This is not currently implemented - 此功能尚未實現 + + Alt+Shift+7 + - - Column Mode... - 列編輯模式... + + Unfold Level 8 + - - Export as HTML... - 匯出為 HTML... + + Alt+Shift+8 + - - Export as RTF... - 匯出為 RTF... + + Unfold Level 9 + - - Copy as HTML - 複製為 HTML + + Alt+Shift+9 + - - Copy as RTF - 複製為 RTF + Alt+C + Alt+C - - Base 64 Encode - Base 64 編碼 + + Export as HTML... + 匯出為 HTML... - - URL Encode - URL 編碼 + + Export as RTF... + 匯出為 RTF... - - Base 64 Decode - Base 64 解碼 + + Copy as HTML + 複製為 HTML - - URL Decode - URL 解碼 + + Copy as RTF + 複製為 RTF - - Copy URL - 複製 URL + + Base 64 Encode + Base 64 編碼 - - Remove Empty Lines - 移除空行 + + URL Encode + URL 編碼 - - - Show in Explorer - 在檔案總管中顯示 + + Base 64 Decode + Base 64 解碼 - - Open %1 Here - Open %1 Here + + URL Decode + URL 解碼 - - Toggle Bookmark - 切換書籤 + + Copy URL + 複製 URL - - Ctrl+F2 - Ctrl+F2 + + Remove Empty Lines + 移除空行 - - Next Bookmark - 下一個書籤 + + + Show in Explorer + 在檔案總管中顯示 - - F2 - F2 + + Open Command Prompt Here + 在此開啟命令提示字元 - - Previous Bookmark - 上一個書籤 + + Toggle Bookmark + 切換書籤 - - Shift+F2 - Shift+F2 + + Ctrl+F2 + Ctrl+F2 - - Clear Bookmarks - 清除書籤 + + Next Bookmark + 下一個書籤 - - Invert Bookmarks - 反轉書籤 + + F2 + F2 - - Next Tab - 下一個分頁 + + Previous Bookmark + 上一個書籤 - - Ctrl+Tab - Ctrl+Tab + + Shift+F2 + Shift+F2 - - Previous Tab - 上一個分頁 + + Clear Bookmarks + 清除書籤 - - Ctrl+Shift+Tab - Ctrl+Shift+Tab + + Invert Bookmarks + 反轉書籤 - - Fold Level 1 - 摺疊層級 1 + + About Qt + 關於 Qt - - Alt+1 - Alt+1 + + + Export As + 匯出為 - - Fold Level 2 - 摺疊層級 2 + + Copy As + 複製為 - - Alt+2 - Alt+2 + + Encoding/Decoding + 編碼/解碼 - - Fold Level 3 - 摺疊層級 3 + + About Notepad Next + 關於 Notepad Next - - Alt+3 - Alt+3 + + Show Whitespace + 顯示空格 - - Fold Level 4 - 摺疊層級 4 + + Show End of Line + 顯示行尾 - - Alt+4 - Alt+4 + + Show All Characters + 顯示所有字元 - - Unfold Level 1 - 展開層級 1 + + Show Indent Guide + 顯示縮排指引 - - Alt+Shift+1 - Alt+Shift+1 + + Show Wrap Symbol + 顯示換行符號 - - Unfold Level 2 - 展開層級 2 + + Word Wrap + 自動換行 - - Alt+Shift+2 - Alt+Shift+2 + + Restore Recently Closed File + 恢復最近關閉的檔案 - - Unfold Level 3 - 展開層級 3 + + Ctrl+Shift+T + Ctrl+Shift+T - - Alt+Shift+3 - Alt+Shift+3 + + Open All Recent Files + 開啟所有最近的檔案 - - Unfold Level 4 - 展開層級 4 + + Clear Recent Files List + 清除最近開啟的檔案清單 - - Alt+Shift+4 - Alt+Shift+4 + + &Find... + 尋找(&F)... - - Fold All - 全部摺疊 + + Ctrl+F + Ctrl+F - - Alt+0 - Alt+0 + + Find in Files... + 在檔案中尋找... - - Unfold All - 全部展開 + + Find &Next + 尋找下一個(&N) - - Alt+Shift+0 - Alt+Shift+0 + + F3 + F3 - - Fold Level 5 - 摺疊層級 5 + + Find &Previous + 尋找上一個(&P) - - Alt+5 - Alt+5 + + &Replace... + 取代(&R)... - - Fold Level 6 - 摺疊層級 6 + + Ctrl+H + Ctrl+H - - Alt+6 - Alt+6 + + Full Screen + 全螢幕 - - Fold Level 7 - 摺疊層級 7 + + F11 + F11 - - Alt+7 - Alt+7 + + + Start Recording + 開始錄製 - - Fold Level 8 - 摺疊層級 8 + + Playback + 播放 - - Alt+8 - Alt+8 + + Ctrl+Shift+P + Ctrl+Shift+P - - Fold Level 9 - 摺疊層級 9 + + Save Current Recorded Macro... + 儲存目前錄製的巨集... - - Alt+9 - Alt+9 + + Run a Macro Multiple Times... + 多次執行巨集... - - Unfold Level 5 - 展開層級 5 + + Preferences... + 偏好設定... - - Alt+Shift+5 - Alt+Shift+5 + + Quick Find + 快速尋找 - - Unfold Level 6 - 展開層級 6 + + Ctrl+Alt+I + Ctrl+Alt+I - - Alt+Shift+6 - Alt+Shift+6 + + Select Next Instance + 選擇下一個實例 - - Unfold Level 7 - 展開層級 7 + + Ctrl+D + Ctrl+D - - Alt+Shift+7 - Alt+Shift+7 + + Move to Trash... + 移至垃圾桶... - - Unfold Level 8 - 展開層級 8 + + Move to Trash + 移至垃圾桶 - - Alt+Shift+8 - Alt+Shift+8 + + Check for Updates... + 檢查更新... - - Unfold Level 9 - 展開層級 9 + + &Go to Line... + 跳轉到行(&G)... - - Alt+Shift+9 - Alt+Shift+9 + + Ctrl+G + Ctrl+G - - - Toggle Overtype - Toggle Overtype + + Print... + 列印... - - Ins - Ins + + Ctrl+P + Ctrl+P - - Debug Info... - Debug Info... + + Open Folder as Workspace... + 以工作區方式開啟資料夾... - - Cut Bookmarked Lines - Cut Bookmarked Lines + + Go to line + 跳轉到行 - - Copy Bookmarked Lines - Copy Bookmarked Lines + + Line Number (1 - %1) + 行號(1 - %1) - - Delete Bookmarked Lines - Delete Bookmarked Lines + + Stop Recording + 停止錄製 - - Mark Style 1 - Mark Style 1 + + New %1 + 新檔案 %1 - - Mark Style 2 - Mark Style 2 + + Create File + 建立檔案 - - Clear Style 1 - Clear Style 1 + + <b>%1</b> does not exist. Do you want to create it? + <b>%1</b> 尚不存在,你想要建立一個嗎? - - Clear Style 2 - Clear Style 2 + + + Save file <b>%1</b>? + 儲存檔案 <b>%1</b>? - - Mark Style 3 - Mark Style 3 + + + Save File + 儲存檔案 - - Clear Style 3 - Clear Style 3 + + Open Folder as Workspace + 以工作區方式開啟資料夾 - - - Clear All Styles - Clear All Styles + + Reload File + 重新載入檔案 - - Remove Duplicate Lines - Remove Duplicate Lines + + Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. + 你確定要重新載入 <b>%1</b>?任何未儲存的修改都會遺失。 - - Remove Consecutive Duplicate Lines - Remove Consecutive Duplicate Lines + + Administrator + - - Sort Lines Ascending - + + Error Saving File + 儲存檔案時出錯 - - Sort Lines Descending - + + Save a Copy As + 副本另存為 - - Sort Lines Ascending (Case-Insensitive) - + + + Rename + 重新命名 - - Sort Lines Descending (Case-Insensitive) - + + Name: + 巨集名稱: - - Sort Lines by Length Ascending - + + Delete File + 刪除檔案 - - Sort Lines by Length Descending - + + Are you sure you want to move <b>%1</b> to the trash? + 你確定要將 <b>%1</b> 移至垃圾桶? - - Reverse Line Order - + + Error Deleting File + 刪除檔案時出錯 - - Go to line - 跳轉到行 + + Something went wrong deleting <b>%1</b>? + 刪除 <b>%1</b> 時出錯了? - - Line Number (1 - %1) - 行號(1 - %1) + + An error occurred when saving <b>%1</b><br><br>Error: %2 + 儲存 <b>%1</b> 時發生了錯誤<br><br>錯誤:%2 - - Stop Recording - 停止錄製 + + Zoom: %1% + - - Debug Info - Debug Info + + No updates are available at this time. + 目前沒有可用的更新。 + + + PreferencesDialog - - New %1 - 新檔案 %1 + + Preferences + 偏好設定 - - Create File - 建立檔案 + + Show menu bar + - - <b>%1</b> does not exist. Do you want to create it? - <b>%1</b> 目前不存在,你想要建立一個嗎? + + Show toolbar + - - - Save file <b>%1</b>? - 儲存檔案 <b>%1</b>? + + Show status bar + - - - Save File - 儲存檔案 + + Restore previous session + - - Open Folder as Workspace - 以工作區方式開啟資料夾 + + Temporary files + - - - Reload File - 重新載入檔案 + + Translation: + - - Are you sure you want to reload <b>%1</b>? Any unsaved changes will be lost. - 你確定要重新載入 <b>%1</b>?任何未儲存的修改都會遺失。 + + Exit on last tab closed + - - Save a Copy As - 副本另存為 + + Default Font + - - - Rename - 重新命名 + + Font + - - Name: - 巨集名稱: + + Font Size + - - Delete File - 刪除檔案 + + pt + - - Are you sure you want to move <b>%1</b> to the trash? - 你確定要將 <b>%1</b> 移至垃圾桶? + + TextLabel + 文字標籤 - - Error Deleting File - 刪除檔案時出錯 + + An application restart is required to apply certain settings. + - - Something went wrong deleting <b>%1</b>? - 刪除 <b>%1</b> 時出錯了? + Menu Bar + 選單列 - - Administrator - Administrator + Tool Bar + 工具列 - - <b>%1</b> has been modified by another program. Do you want to reload it? - <b>%1</b> has been modified by another program. Do you want to reload it? + Status Bar + 狀態列 - - Read error - Read error + Restore Previous Session + 恢復先前的工作階段 - - Write error - Write error + + Unsaved changes + 未儲存的變更 - - Fatal error - Fatal error + Temp Files + 暫存檔案 - - Resource error - Resource error + + Combine search results + 合併搜尋結果 - - Open error - Open error + + Warning + 警告 - - Abort error - Abort error + + This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. + 此功能為實驗性質,對於重要的工作可能並不安全,可能導致資料遺失,請自行承擔風險。 - - Timeout error - Timeout error + + <System Default> + + + + QObject - - Unspecified error - Unspecified error + + List All Tabs + 列出所有分頁 - - Remove error - Remove error + + Detach Group + 分離群組 - - Rename error - Rename error + + Minimize + - - Position error - Position error + Close Active Tab + 關閉活躍分頁 - - Resize error - Resize error + Close Group + 關閉群組 - - Permissions error - Permissions error + + Close Tab + 關閉分頁 + + + QuickFindWidget - - Copy error - Copy error + + Frame + - - Unknown error (%1) - Unknown error (%1) + + Match case + 區分大小寫 - - Error Saving File - 儲存檔案時出錯 + + Aa + Aa - - An error occurred when saving <b>%1</b><br><br>Error: %2 - 儲存 <b>%1</b> 時發生了錯誤<br><br>錯誤:%2 + + Match whole word + 全字符合 - - Zoom: %1% - Zoom: %1% + + |A| + |A| - - No updates are available at this time. - 目前沒有可用的更新。 + + Use regular expression + 使用正規表達式 - - - PreferencesDialog - - Preferences - 偏好設定 + + . * + . * - - Show menu bar - 顯示選單列 + + Alt+E + Alt+E - - Show toolbar - 顯示工具列 + + Find... + 尋找... - - Show status bar - 顯示狀態列 + + %L1/%L2 + + + + SearchResultsDock - - Restore previous session - 還原上一次的工作階段 + + Search Results + 搜尋結果 - - Unsaved changes - 未儲存的變更 + + Collapse All + 全部摺疊 - - Temporary files - 暫存檔案 + + Expand All + 全部展開 - - Recenter find/replace dialog when opened - Recenter find/replace dialog when opened + + Delete Entry + 刪除項目 - - Combine search results - 合併搜尋結果 + + Delete All + 全部刪除 + + + Updater - - Translation: - 翻譯: + + Would you like to download the update now? + 您現在想要下載更新嗎? - - Exit on last tab closed - 關閉最後一個分頁時結束程式 + + Would you like to download the update now? This is a mandatory update, exiting now will close the application + 您現在想要下載更新嗎?這是一個必須的更新,現在退出將會關閉應用程式 - - Default Font - 預設字體 + + Version %1 of %2 has been released! + %2 的版本 %1 已經發布! - - Font - 字體 + + No updates are available for the moment + 目前沒有可用的更新 - - Font Size - 字體大小 + + Congratulations! You are running the latest version of %1 + 恭喜!您正在執行最新版本的 %1 + + + ads::CAutoHideTab - - pt - + + Detach + 分離 - - Default Line Endings - Default Line Endings + + Pin To... + - - Highlight URLs - Highlight URLs + + Top + - - Show Line Numbers - Show Line Numbers + + Left + - - - Default Directory - Default Directory + + Right + - - Follow Current Document - Follow Current Document + + Bottom + - - Last Used Directory - Last Used Directory + + Unpin (Dock) + - - ... - ... + + Close + 關閉 + + + ads::CDockAreaTitleBar - - TextLabel - 文字標籤 + + Detach Group + 分離群組 - - An application restart is required to apply certain settings. - 某些設定需要重新啟動應用程式才能生效。 + + Detach + 分離 - - Warning - 警告 + + + Unpin (Dock) + - - This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk. - 此功能為實驗性質,對於重要的工作可能並不安全,可能導致資料遺失,請自行承擔風險。 + + + Pin Group + - - System Default - System Default + + Pin Group To... + - - Windows (CR LF) - Windows (CR LF) + + Top + - - Linux (LF) - Linux (LF) + + Left + - - Macintosh (CR) - Macintosh (CR) + + Right + - - <System Default> - <系統預設> + + Bottom + - - - QuickFindWidget - - Frame - Frame + + + Minimize + - - Find... - 尋找... + + + + Close + 關閉 - - Match case - 區分大小寫 + + + Close Group + 關閉群組 - - Aa - Aa + + Close Other Groups + 關閉其他群組 - - Match whole word - 全字符合 + + Pin Active Tab (Press Ctrl to Pin Group) + - - |A| - |A| + + Close Active Tab + 關閉活躍分頁 + + + ads::CDockManager - - Use regular expression - 使用正規表達式 + + Show View + 顯示畫面 + + + ads::CDockWidgetTab - - . * - . * + + Detach + 分離 - - Alt+E - Alt+E + + Pin + - - %L1/%L2 - %L1/%L2 + + Pin To... + - - - SearchResultsDock - - Search Results - 搜尋結果 + + Top + - - Copy Results to Clipboard - Copy Results to Clipboard + + Left + - - Collapse All - 全部摺疊 + + Right + - - Expand All - 全部展開 + + Bottom + - - Delete Entry - 刪除項目 + + Close + 關閉 - - Delete All - 全部刪除 + + Close Others + 關閉其他 - + diff --git a/icon/NotepadNext.icns b/icon/NotepadNext.icns index 6fbd4d56d..988166566 100644 Binary files a/icon/NotepadNext.icns and b/icon/NotepadNext.icns differ diff --git a/icon/NotepadNext.ico b/icon/NotepadNext.ico index 00c07b4f4..9f5cb62a2 100644 Binary files a/icon/NotepadNext.ico and b/icon/NotepadNext.ico differ diff --git a/icon/svg_to_ico.bat b/icon/svg_to_ico.bat index 54a3c747b..49b2707ae 100644 --- a/icon/svg_to_ico.bat +++ b/icon/svg_to_ico.bat @@ -1,14 +1,20 @@ -@echo off -set ICON_SIZES=16 32 48 64 128 256 +"C:\Program Files\Inkscape\bin\inkscape.exe" -w 16 -h 16 --export-type="png" --export-filename="nn16.png" NotepadNext.svg +"C:\Program Files\Inkscape\bin\inkscape.exe" -w 32 -h 32 --export-type="png" --export-filename="nn32.png" NotepadNext.svg +"C:\Program Files\Inkscape\bin\inkscape.exe" -w 48 -h 48 --export-type="png" --export-filename="nn48.png" NotepadNext.svg +"C:\Program Files\Inkscape\bin\inkscape.exe" -w 64 -h 64 --export-type="png" --export-filename="nn64.png" NotepadNext.svg +"C:\Program Files\Inkscape\bin\inkscape.exe" -w 128 -h 128 --export-type="png" --export-filename="nn128.png" NotepadNext.svg +"C:\Program Files\Inkscape\bin\inkscape.exe" -w 128 -h 128 --export-type="png" --export-filename="nn512.png" NotepadNext.svg +".\ImageMagick\magick" convert -background transparent nn16.png nn32.png nn48.png nn64.png nn128.png nn512.png NotepadNext.ico -for %%s in (%ICON_SIZES%) do ( - echo Exporting %%sx%%s PNG... - "C:\Program Files\Inkscape\bin\inkscape.exe" NotepadNext.svg -w %%s -h %%s --export-type=png --export-filename=nn%%s.png -) +del nn16.png +del nn32.png +del nn48.png +del nn64.png +del nn128.png +del nn512.png -".\ImageMagick\magick" convert -background transparent nn16.png nn32.png nn48.png nn64.png nn128.png nn256.png NotepadNext.ico +"C:\Program Files\Inkscape\bin\inkscape.exe" --export-type="png" --export-dpi=96 --export-background-opacity=0 NotepadNext.svg -for %%s in (%ICON_SIZES%) do del nn%%s.png +".\png2icons.exe" NotepadNext.png NotepadNext -icns -"C:\Program Files\Inkscape\bin\inkscape.exe" NotepadNext.svg --export-type=png --export-dpi=96 --export-background-opacity=0 copy NotepadNext.png ..\src\NotepadNext\icons\NotepadNext.png diff --git a/installer/installer.nsi b/installer/installer.nsi index 6f9a286d2..7689cc9b1 100644 --- a/installer/installer.nsi +++ b/installer/installer.nsi @@ -303,7 +303,7 @@ Section "Uninstall" DeleteRegKey SHCTX "Software\Classes\*\shell\NotepadNext" # Remove application registration - DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\App Paths\NotepadNext.exe" + DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\App Paths\NotepadNext.exe" "" "$INSTDIR\NotepadNext.exe" # Remove registered verbs DeleteRegKey SHCTX "Software\Classes\Applications\NotepadNext.exe" diff --git a/src/Config.pri b/src/Config.pri new file mode 100644 index 000000000..091a8c14f --- /dev/null +++ b/src/Config.pri @@ -0,0 +1,40 @@ +# This file is part of Notepad Next. +# Copyright 2019 Justin Dailey +# +# Notepad Next 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, either version 3 of the License, or +# (at your option) any later version. +# +# Notepad Next 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. +# +# You should have received a copy of the GNU General Public License +# along with Notepad Next. If not, see . + + +include(Version.pri) + +# Add custom defines +DEFINES += APP_VERSION='"\\\"$$APP_VERSION\\\""' +DEFINES += APP_COPYRIGHT='"\\\"$$APP_COPYRIGHT\\\""' + +!isEmpty(DISTRIBUTION) { + DEFINES += APP_DISTRIBUTION='"\\\" ($$DISTRIBUTION)\\\""' +} +else { + DEFINES += APP_DISTRIBUTION='"\\\"\\\""' +} + +CONFIG += c++1z +CONFIG -= debug_and_release debug_and_release_target + +# Controls if we want to define our own regex engine using QRegularExpression +DEFINES += SCI_OWNREGEX + +DEFINES += ADS_STATIC + +msvc:QMAKE_CXXFLAGS += /guard:cf +msvc:QMAKE_LFLAGS += /guard:cf diff --git a/src/LuaBridge/List.h b/src/LuaBridge/List.h new file mode 100644 index 000000000..66e0d8fb6 --- /dev/null +++ b/src/LuaBridge/List.h @@ -0,0 +1,55 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + static void push (lua_State* L, std::list const& list) + { + lua_createtable (L, static_cast (list.size ()), 0); + typename std::list ::const_iterator item = list.begin (); + for (std::size_t i = 1; i <= list.size (); ++i) + { + lua_pushinteger (L, static_cast (i)); + Stack ::push (L, *item); + lua_settable (L, -3); + ++item; + } + } + + static std::list get (lua_State* L, int index) + { + if (!lua_istable (L, index)) + { + luaL_error (L, "#%d argument must be a table", index); + } + + std::list list; + + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + list.push_back (Stack ::get (L, -1)); + lua_pop (L, 1); + } + return list; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/src/LuaBridge/LuaBridge.h b/src/LuaBridge/LuaBridge.h new file mode 100644 index 000000000..866acc39c --- /dev/null +++ b/src/LuaBridge/LuaBridge.h @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +// All #include dependencies are listed here +// instead of in the individual header files. +// + +#define LUABRIDGE_MAJOR_VERSION 2 +#define LUABRIDGE_MINOR_VERSION 3 +#define LUABRIDGE_VERSION 203 + +#ifndef LUA_VERSION_NUM +#error "Lua headers must be included prior to LuaBridge ones" +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/src/LuaBridge/Map.h b/src/LuaBridge/Map.h new file mode 100644 index 000000000..a36d269a6 --- /dev/null +++ b/src/LuaBridge/Map.h @@ -0,0 +1,56 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + typedef std::map Map; + + static void push (lua_State* L, const Map& map) + { + lua_createtable (L, 0, static_cast (map.size ())); + typedef typename Map::const_iterator ConstIter; + for (ConstIter i = map.begin (); i != map.end (); ++i) + { + Stack ::push (L, i->first); + Stack ::push (L, i->second); + lua_settable (L, -3); + } + } + + static Map get (lua_State* L, int index) + { + if (!lua_istable (L, index)) + { + luaL_error (L, "#%d argument must be a table", index); + } + + Map map; + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + map.emplace (Stack ::get (L, -2), Stack ::get (L, -1)); + lua_pop (L, 1); + } + return map; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/src/LuaBridge/RefCountedObject.h b/src/LuaBridge/RefCountedObject.h new file mode 100644 index 000000000..6a0c7f43d --- /dev/null +++ b/src/LuaBridge/RefCountedObject.h @@ -0,0 +1,385 @@ +//============================================================================== +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + Copyright 2004-11 by Raw Material Software Ltd. + + This is a derivative work used by permission from part of + JUCE, available at http://www.rawaterialsoftware.com + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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. + + This file incorporates work covered by the following copyright and + permission notice: + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. +*/ +//============================================================================== + +#pragma once + +#include +#include + +#include + +namespace luabridge { + +//============================================================================== +/** + Adds reference-counting to an object. + + To add reference-counting to a class, derive it from this class, and + use the RefCountedObjectPtr class to point to it. + + e.g. @code + class MyClass : public RefCountedObjectType + { + void foo(); + + // This is a neat way of declaring a typedef for a pointer class, + // rather than typing out the full templated name each time.. + typedef RefCountedObjectPtr Ptr; + }; + + MyClass::Ptr p = new MyClass(); + MyClass::Ptr p2 = p; + p = 0; + p2->foo(); + @endcode + + Once a new RefCountedObjectType has been assigned to a pointer, be + careful not to delete the object manually. +*/ +template +class RefCountedObjectType +{ +public: + //============================================================================== + /** Increments the object's reference count. + + This is done automatically by the smart pointer, but is public just + in case it's needed for nefarious purposes. + */ + inline void incReferenceCount() const + { + ++refCount; + } + + /** Decreases the object's reference count. + + If the count gets to zero, the object will be deleted. + */ + inline void decReferenceCount() const + { + assert (getReferenceCount() > 0); + + if (--refCount == 0) + delete this; + } + + /** Returns the object's current reference count. + * @returns The reference count. + */ + inline int getReferenceCount() const + { + return static_cast (refCount); + } + +protected: + //============================================================================== + /** Creates the reference-counted object (with an initial ref count of zero). */ + RefCountedObjectType() : refCount () + { + } + + /** Destructor. */ + virtual ~RefCountedObjectType() + { + // it's dangerous to delete an object that's still referenced by something else! + assert (getReferenceCount() == 0); + } + +private: + //============================================================================== + CounterType mutable refCount; +}; + +//============================================================================== + +/** Non thread-safe reference counted object. + + This creates a RefCountedObjectType that uses a non-atomic integer + as the counter. +*/ +typedef RefCountedObjectType RefCountedObject; + +//============================================================================== +/** + A smart-pointer class which points to a reference-counted object. + + The template parameter specifies the class of the object you want to point + to - the easiest way to make a class reference-countable is to simply make + it inherit from RefCountedObjectType, but if you need to, you could roll + your own reference-countable class by implementing a pair of methods called + incReferenceCount() and decReferenceCount(). + + When using this class, you'll probably want to create a typedef to + abbreviate the full templated name - e.g. + + @code + + typedef RefCountedObjectPtr MyClassPtr; + + @endcode +*/ +template +class RefCountedObjectPtr +{ +public: + /** The class being referenced by this pointer. */ + typedef ReferenceCountedObjectClass ReferencedType; + + //============================================================================== + /** Creates a pointer to a null object. */ + inline RefCountedObjectPtr() : referencedObject (0) + { + } + + /** Creates a pointer to an object. + This will increment the object's reference-count if it is non-null. + + @param refCountedObject A reference counted object to own. + */ + inline RefCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject) + : referencedObject (refCountedObject) + { + if (refCountedObject != 0) + refCountedObject->incReferenceCount(); + } + + /** Copies another pointer. + This will increment the object's reference-count (if it is non-null). + + @param other Another pointer. + */ + inline RefCountedObjectPtr (const RefCountedObjectPtr& other) + : referencedObject (other.referencedObject) + { + if (referencedObject != 0) + referencedObject->incReferenceCount(); + } + +#ifdef LUABRIDGE_CXX11 + /** + Takes-over the object from another pointer. + + @param other Another pointer. + */ + inline RefCountedObjectPtr (RefCountedObjectPtr&& other) + : referencedObject (other.referencedObject) + { + other.referencedObject = 0; + } +#endif + + /** Copies another pointer. + This will increment the object's reference-count (if it is non-null). + + @param other Another pointer. + */ + template + inline RefCountedObjectPtr (const RefCountedObjectPtr& other) + : referencedObject (static_cast (other.getObject())) + { + if (referencedObject != 0) + referencedObject->incReferenceCount(); + } + + /** Changes this pointer to point at a different object. + + The reference count of the old object is decremented, and it might be + deleted if it hits zero. The new object's count is incremented. + + @param other A pointer to assign from. + @returns This pointer. + */ + RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other) + { + return operator= (other.referencedObject); + } + + /** Changes this pointer to point at a different object. + The reference count of the old object is decremented, and it might be + deleted if it hits zero. The new object's count is incremented. + + @param other A pointer to assign from. + @returns This pointer. + */ + template + RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other) + { + return operator= (static_cast (other.getObject())); + } + +#ifdef LUABRIDGE_CXX11 + /** + Takes-over the object from another pointer. + + @param other A pointer to assign from. + @returns This pointer. + */ + RefCountedObjectPtr& operator= (RefCountedObjectPtr&& other) + { + std::swap (referencedObject, other.referencedObject); + return *this; + } +#endif + + /** Changes this pointer to point at a different object. + The reference count of the old object is decremented, and it might be + deleted if it hits zero. The new object's count is incremented. + + @param newObject A reference counted object to own. + @returns This pointer. + */ + RefCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject) + { + if (referencedObject != newObject) + { + if (newObject != 0) + newObject->incReferenceCount(); + + ReferenceCountedObjectClass* const oldObject = referencedObject; + referencedObject = newObject; + + if (oldObject != 0) + oldObject->decReferenceCount(); + } + + return *this; + } + + /** Destructor. + This will decrement the object's reference-count, and may delete it if it + gets to zero. + */ + ~RefCountedObjectPtr() + { + if (referencedObject != 0) + referencedObject->decReferenceCount(); + } + + /** Returns the object that this pointer references. + The returned pointer may be null. + + @returns The pointee. + */ + operator ReferenceCountedObjectClass*() const + { + return referencedObject; + } + + /** Returns the object that this pointer references. + The returned pointer may be null. + + @returns The pointee. + */ + ReferenceCountedObjectClass* operator->() const + { + return referencedObject; + } + + /** Returns the object that this pointer references. + The returned pointer may be null. + + @returns The pointee. + */ + ReferenceCountedObjectClass* getObject() const + { + return referencedObject; + } + +private: + //============================================================================== + ReferenceCountedObjectClass* referencedObject; +}; + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (const RefCountedObjectPtr& object1, ReferenceCountedObjectClass* const object2) +{ + return object1.getObject() == object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (const RefCountedObjectPtr& object1, const RefCountedObjectPtr& object2) +{ + return object1.getObject() == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (ReferenceCountedObjectClass* object1, RefCountedObjectPtr& object2) +{ + return object1 == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const RefCountedObjectPtr& object1, const ReferenceCountedObjectClass* object2) +{ + return object1.getObject() != object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const RefCountedObjectPtr& object1, RefCountedObjectPtr& object2) +{ + return object1.getObject() != object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr& object2) +{ + return object1 != object2.getObject(); +} + +//============================================================================== + +template +struct ContainerTraits > +{ + typedef T Type; + + static T* get (RefCountedObjectPtr const& c) + { + return c.getObject (); + } +}; + +//============================================================================== + +} // namespace luabridge diff --git a/src/LuaBridge/RefCountedPtr.h b/src/LuaBridge/RefCountedPtr.h new file mode 100644 index 000000000..680809087 --- /dev/null +++ b/src/LuaBridge/RefCountedPtr.h @@ -0,0 +1,249 @@ +//============================================================================== +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { + +namespace detail { + +//============================================================================== +/** + Support for our RefCountedPtr. +*/ +struct RefCountedPtrBase +{ + // Declaration of container for the refcounts + typedef std::unordered_map RefCountsType; + +protected: + RefCountsType& getRefCounts () const + { + static RefCountsType refcounts; + return refcounts ; + } +}; + +} // namespace detail + +//============================================================================== +/** + A reference counted smart pointer. + + The api is compatible with boost::RefCountedPtr and std::RefCountedPtr, in the + sense that it implements a strict subset of the functionality. + + This implementation uses a hash table to look up the reference count + associated with a particular pointer. + + @tparam T The class type. + + @todo Decompose RefCountedPtr using a policy. At a minimum, the underlying + reference count should be policy based (to support atomic operations) + and the delete behavior should be policy based (to support custom + disposal methods). + + @todo Provide an intrusive version of RefCountedPtr. +*/ +template +class RefCountedPtr : private detail::RefCountedPtrBase +{ +public: + template + struct rebind + { + typedef RefCountedPtr other; + }; + + /** Construct as nullptr or from existing pointer to T. + + @param p The optional, existing pointer to assign from. + */ + RefCountedPtr (T* p = 0) : m_p (p) + { + ++getRefCounts () [m_p]; + } + + /** Construct from another RefCountedPtr. + + @param rhs The RefCountedPtr to assign from. + */ + RefCountedPtr (RefCountedPtr const& rhs) : m_p (rhs.get()) + { + ++getRefCounts () [m_p]; + } + + /** Construct from a RefCountedPtr of a different type. + + @invariant A pointer to U must be convertible to a pointer to T. + + @tparam U The other object type. + @param rhs The RefCountedPtr to assign from. + */ + template + RefCountedPtr (RefCountedPtr const& rhs) : m_p (static_cast (rhs.get())) + { + ++getRefCounts () [m_p]; + } + + /** Release the object. + + If there are no more references then the object is deleted. + */ + ~RefCountedPtr () + { + reset(); + } + + /** Assign from another RefCountedPtr. + + @param rhs The RefCountedPtr to assign from. + @returns A reference to the RefCountedPtr. + */ + RefCountedPtr & operator= (RefCountedPtr const& rhs) + { + if (m_p != rhs.m_p) + { + reset (); + m_p = rhs.m_p; + ++getRefCounts () [m_p]; + } + return *this; + } + + /** Assign from another RefCountedPtr of a different type. + + @note A pointer to U must be convertible to a pointer to T. + + @tparam U The other object type. + @param rhs The other RefCountedPtr to assign from. + @returns A reference to the RefCountedPtr. + */ + template + RefCountedPtr & operator= (RefCountedPtr const& rhs) + { + reset (); + m_p = static_cast (rhs.get()); + ++getRefCounts () [m_p]; + return *this; + } + + /** Retrieve the raw pointer. + + @returns A pointer to the object. + */ + T* get () const + { + return m_p; + } + + /** Retrieve the raw pointer. + + @returns A pointer to the object. + */ + T* operator* () const + { + return m_p; + } + + /** Retrieve the raw pointer. + + @returns A pointer to the object. + */ + T* operator-> () const + { + return m_p; + } + + /** Determine the number of references. + + @note This is not thread-safe. + + @returns The number of active references. + */ + long use_count () const + { + return getRefCounts () [m_p]; + } + + /** Release the pointer. + + The reference count is decremented. If the reference count reaches + zero, the object is deleted. + */ + void reset () + { + if (m_p != 0) + { + if (--getRefCounts () [m_p] <= 0) + delete m_p; + + m_p = 0; + } + } + +private: + T* m_p; +}; + +template +bool operator== (const RefCountedPtr & lhs, const RefCountedPtr & rhs) +{ + return lhs.get () == rhs.get (); +} + +template +bool operator!= (const RefCountedPtr & lhs, const RefCountedPtr & rhs) +{ + return lhs.get() != rhs.get(); +} + +//============================================================================== + +// forward declaration +template +struct ContainerTraits; + +template +struct ContainerTraits > +{ + typedef T Type; + + static T* get (RefCountedPtr const& c) + { + return c.get (); + } +}; + +} // namespace luabridge diff --git a/src/LuaBridge/UnorderedMap.h b/src/LuaBridge/UnorderedMap.h new file mode 100644 index 000000000..78a7aceef --- /dev/null +++ b/src/LuaBridge/UnorderedMap.h @@ -0,0 +1,55 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2019, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + typedef std::unordered_map Map; + + static void push (lua_State* L, const Map& map) + { + lua_createtable (L, 0, static_cast (map.size ())); + typedef typename Map::const_iterator ConstIter; + for (ConstIter i = map.begin (); i != map.end (); ++i) + { + Stack ::push (L, i->first); + Stack ::push (L, i->second); + lua_settable (L, -3); + } + } + + static Map get (lua_State* L, int index) + { + if (!lua_istable (L, index)) + { + luaL_error (L, "#%d argument must be a table", index); + } + + Map map; + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + map.emplace (Stack ::get (L, -2), Stack ::get (L, -1)); + lua_pop (L, 1); + } + return map; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/src/LuaBridge/Vector.h b/src/LuaBridge/Vector.h new file mode 100644 index 000000000..cc8031364 --- /dev/null +++ b/src/LuaBridge/Vector.h @@ -0,0 +1,54 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + static void push (lua_State* L, std::vector const& vector) + { + lua_createtable (L, static_cast (vector.size ()), 0); + for (std::size_t i = 0; i < vector.size (); ++i) + { + lua_pushinteger (L, static_cast (i + 1)); + Stack ::push (L, vector [i]); + lua_settable (L, -3); + } + } + + static std::vector get (lua_State* L, int index) + { + if (!lua_istable (L, index)) + { + luaL_error (L, "#%d argument must be a table", index); + } + + std::vector vector; + vector.reserve (static_cast (get_length (L, index))); + + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + vector.push_back (Stack ::get (L, -1)); + lua_pop (L, 1); + } + return vector; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_istable (L, index); + } +}; + +} // namespace luabridge diff --git a/src/LuaBridge/detail/CFunctions.h b/src/LuaBridge/detail/CFunctions.h new file mode 100644 index 000000000..7664f8b6f --- /dev/null +++ b/src/LuaBridge/detail/CFunctions.h @@ -0,0 +1,498 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { +namespace detail { + +// We use a structure so we can define everything in the header. +// +struct CFunc +{ + static void addGetter (lua_State* L, const char* name, int tableIndex) + { + assert (lua_istable (L, tableIndex)); + assert (lua_iscfunction (L, -1)); // Stack: getter + + lua_rawgetp (L, tableIndex, getPropgetKey ()); // Stack: getter, propget table (pg) + lua_pushvalue (L, -2); // Stack: getter, pg, getter + rawsetfield (L, -2, name); // Stack: getter, pg + lua_pop (L, 2); // Stack: - + } + + static void addSetter (lua_State* L, const char* name, int tableIndex) + { + assert (lua_istable (L, tableIndex)); + assert (lua_iscfunction (L, -1)); // Stack: setter + + lua_rawgetp (L, tableIndex, getPropsetKey ()); // Stack: setter, propset table (ps) + lua_pushvalue (L, -2); // Stack: setter, ps, setter + rawsetfield (L, -2, name); // Stack: setter, ps + lua_pop (L, 2); // Stack: - + } + + //---------------------------------------------------------------------------- + /** + __index metamethod for a namespace or class static and non-static members. + Retrieves functions from metatables and properties from propget tables. + Looks through the class hierarchy if inheritance is present. + */ + static int indexMetaMethod (lua_State* L) + { + assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name + + lua_getmetatable (L, 1); // Stack: class/const table (mt) + assert (lua_istable (L, -1)); + + for (;;) + { + lua_pushvalue (L, 2); // Stack: mt, field name + lua_rawget (L, -2); // Stack: mt, field | nil + + if (lua_iscfunction (L, -1)) // Stack: mt, field + { + lua_remove (L, -2); // Stack: field + return 1; + } + + assert (lua_isnil (L, -1)); // Stack: mt, nil + lua_pop (L, 1); // Stack: mt + + lua_rawgetp (L, -1, getPropgetKey ()); // Stack: mt, propget table (pg) + assert (lua_istable (L, -1)); + + lua_pushvalue (L, 2); // Stack: mt, pg, field name + lua_rawget (L, -2); // Stack: mt, pg, getter | nil + lua_remove (L, -2); // Stack: mt, getter | nil + + if (lua_iscfunction (L, -1)) // Stack: mt, getter + { + lua_remove (L, -2); // Stack: getter + lua_pushvalue (L, 1); // Stack: getter, table | userdata + lua_call (L, 1, 1); // Stack: value + return 1; + } + + assert (lua_isnil (L, -1)); // Stack: mt, nil + lua_pop (L, 1); // Stack: mt + + // It may mean that the field may be in const table and it's constness violation. + // Don't check that, just return nil + + // Repeat the lookup in the parent metafield, + // or return nil if the field doesn't exist. + lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil + + if (lua_isnil (L, -1)) // Stack: mt, nil + { + lua_remove (L, -2); // Stack: nil + return 1; + } + + // Removethe metatable and repeat the search in the parent one. + assert (lua_istable (L, -1)); // Stack: mt, parent mt + lua_remove (L, -2); // Stack: parent mt + } + + // no return + } + + //---------------------------------------------------------------------------- + /** + __newindex metamethod for namespace or class static members. + Retrieves properties from propset tables. + */ + static int newindexStaticMetaMethod (lua_State* L) + { + return newindexMetaMethod (L, false); + } + + //---------------------------------------------------------------------------- + /** + __newindex metamethod for non-static members. + Retrieves properties from propset tables. + */ + static int newindexObjectMetaMethod (lua_State* L) + { + return newindexMetaMethod (L, true); + } + + static int newindexMetaMethod (lua_State* L, bool pushSelf) + { + assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name, new value + + lua_getmetatable (L, 1); // Stack: metatable (mt) + assert (lua_istable (L, -1)); + + for (;;) + { + lua_rawgetp (L, -1, getPropsetKey ()); // Stack: mt, propset table (ps) | nil + + if (lua_isnil (L, -1)) // Stack: mt, nil + { + lua_pop (L, 2); // Stack: - + return luaL_error (L, "No member named '%s'", lua_tostring (L, 2)); + } + + assert (lua_istable (L, -1)); + + lua_pushvalue (L, 2); // Stack: mt, ps, field name + lua_rawget (L, -2); // Stack: mt, ps, setter | nil + lua_remove (L, -2); // Stack: mt, setter | nil + + if (lua_iscfunction (L, -1)) // Stack: mt, setter + { + lua_remove (L, -2); // Stack: setter + if (pushSelf) + { + lua_pushvalue (L, 1); // Stack: setter, table | userdata + } + lua_pushvalue (L, 3); // Stack: setter, table | userdata, new value + lua_call (L, pushSelf ? 2 : 1, 0); // Stack: - + return 0; + } + + assert (lua_isnil (L, -1)); // Stack: mt, nil + lua_pop (L, 1); // Stack: mt + + lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil + + if (lua_isnil (L, -1)) // Stack: mt, nil + { + lua_pop (L, 1); // Stack: - + return luaL_error (L, "No writable member '%s'", lua_tostring (L, 2)); + } + + assert (lua_istable (L, -1)); // Stack: mt, parent mt + lua_remove (L, -2); // Stack: parent mt + // Repeat the search in the parent + } + + // no return + } + + //---------------------------------------------------------------------------- + /** + lua_CFunction to report an error writing to a read-only value. + + The name of the variable is in the first upvalue. + */ + static int readOnlyError (lua_State* L) + { + std::string s; + + s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only"; + + return luaL_error (L, s.c_str ()); + } + + //---------------------------------------------------------------------------- + /** + lua_CFunction to get a variable. + + This is used for global variables or class static data members. + + The pointer to the data is in the first upvalue. + */ + template + static int getVariable (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + T const* ptr = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (ptr != 0); + Stack ::push (L, *ptr); + return 1; + } + + //---------------------------------------------------------------------------- + /** + lua_CFunction to set a variable. + + This is used for global variables or class static data members. + + The pointer to the data is in the first upvalue. + */ + template + static int setVariable (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + T* ptr = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (ptr != 0); + *ptr = Stack ::get (L, 1); + return 0; + } + + //---------------------------------------------------------------------------- + /** + lua_CFunction to call a function with a return value. + + This is used for global functions, global properties, class static methods, + and class static properties. + + The function pointer (lightuserdata) in the first upvalue. + */ + template + struct Call + { + typedef typename FuncTraits ::Params Params; + typedef typename FuncTraits ::ReturnType ReturnType; + + static int f (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + FnPtr fnptr = reinterpret_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::run (L, fnptr); + } + }; + + //---------------------------------------------------------------------------- + /** + lua_CFunction to call a class member function with a return value. + + The member function pointer is in the first upvalue. + The class userdata object is at the top of the Lua stack. + */ + template + struct CallMember + { + typedef typename FuncTraits ::ClassType T; + typedef typename FuncTraits ::Params Params; + typedef typename FuncTraits ::ReturnType ReturnType; + + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + T* const t = Userdata::get (L, 1, false); + MemFnPtr const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::run (L, t, fnptr); + } + }; + + template + struct CallConstMember + { + typedef typename FuncTraits ::ClassType T; + typedef typename FuncTraits ::Params Params; + typedef typename FuncTraits ::ReturnType ReturnType; + + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + T const* const t = Userdata::get (L, 1, true); + MemFnPtr const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::run (L, t, fnptr); + } + }; + + //-------------------------------------------------------------------------- + /** + lua_CFunction to call a class member lua_CFunction. + + The member function pointer is in the first upvalue. + The object userdata ('this') value is at top ot the Lua stack. + */ + template + struct CallMemberCFunction + { + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + typedef int (T::*MFP) (lua_State* L); + T* const t = Userdata::get (L, 1, false); + MFP const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return (t->*fnptr) (L); + } + }; + + template + struct CallConstMemberCFunction + { + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + typedef int (T::*MFP) (lua_State* L); + T const* const t = Userdata::get (L, 1, true); + MFP const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return (t->*fnptr) (L); + } + }; + +#ifdef LUABRIDGE_CXX11 + + //-------------------------------------------------------------------------- + /** + lua_CFunction to call on a object. + + The proxy function pointer (lightuserdata) is in the first upvalue. + The class userdata object is at the top of the Lua stack. + */ + template + struct CallProxyFunction + { + using Params = typename FuncTraits ::Params; + using ReturnType = typename FuncTraits ::ReturnType; + + static int f (lua_State* L) + { + assert (lua_islightuserdata (L, lua_upvalueindex (1))); + auto fnptr = reinterpret_cast (lua_touserdata (L, lua_upvalueindex (1))); + assert (fnptr != 0); + return Invoke ::run (L, fnptr); + } + }; + + template + struct CallProxyFunctor + { + using Params = typename FuncTraits ::Params; + using ReturnType = typename FuncTraits ::ReturnType; + + static int f (lua_State* L) + { + assert (isfulluserdata (L, lua_upvalueindex (1))); + Functor& fn = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); + return Invoke ::run (L, fn); + } + }; + +#endif + + //-------------------------------------------------------------------------- + + // SFINAE Helpers + + template + struct CallMemberFunctionHelper + { + static void add (lua_State* L, char const* name, MemFnPtr mf) + { + new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf); + lua_pushcclosure (L, &CallConstMember ::f, 1); + lua_pushvalue (L, -1); + rawsetfield (L, -5, name); // const table + rawsetfield (L, -3, name); // class table + } + }; + + template + struct CallMemberFunctionHelper + { + static void add (lua_State* L, char const* name, MemFnPtr mf) + { + new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf); + lua_pushcclosure (L, &CallMember ::f, 1); + rawsetfield (L, -3, name); // class table + } + }; + + //-------------------------------------------------------------------------- + /** + __gc metamethod for a class. + */ + template + static int gcMetaMethod (lua_State* L) + { + Userdata* const ud = Userdata::getExact (L, 1); + ud->~Userdata (); + return 0; + } + + /** + __gc metamethod for an arbitrary class. + */ + template + static int gcMetaMethodAny (lua_State* L) + { + assert (isfulluserdata (L, 1)); + T* t = static_cast (lua_touserdata (L, 1)); + t->~T (); + return 0; + } + + //-------------------------------------------------------------------------- + /** + lua_CFunction to get a class data member. + + The pointer-to-member is in the first upvalue. + The class userdata object is at the top of the Lua stack. + */ + template + static int getProperty (lua_State* L) + { + C* const c = Userdata::get (L, 1, true); + T C::** mp = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + try + { + Stack ::push (L, c->**mp); + } + catch (const std::exception& e) + { + luaL_error (L, e.what ()); + } + return 1; + } + + //-------------------------------------------------------------------------- + /** + lua_CFunction to set a class data member. + + The pointer-to-member is in the first upvalue. + The class userdata object is at the top of the Lua stack. + */ + template + static int setProperty (lua_State* L) + { + C* const c = Userdata::get (L, 1, false); + T C::** mp = static_cast (lua_touserdata (L, lua_upvalueindex (1))); + try + { + c->**mp = Stack ::get (L, 2); + } + catch (const std::exception& e) + { + luaL_error (L, e.what ()); + } + return 0; + } +}; + +} // namespace detail + +} // namespace luabridge diff --git a/src/LuaBridge/detail/ClassInfo.h b/src/LuaBridge/detail/ClassInfo.h new file mode 100644 index 000000000..44dcb8b0f --- /dev/null +++ b/src/LuaBridge/detail/ClassInfo.h @@ -0,0 +1,163 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2020, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { +namespace detail { + +/** + * A unique key for a type name in a metatable. + */ +inline const void* getTypeKey () +{ +#ifdef _NDEBUG + static char value; + return &value; +#else + return reinterpret_cast (0x71); +#endif +} + +/** + * The key of a const table in another metatable. + */ +inline const void* getConstKey () +{ +#ifdef _NDEBUG + static char value; + return &value; +#else + return reinterpret_cast (0xc07); +#endif +} + +/** + * The key of a class table in another metatable. + */ +inline const void* getClassKey () +{ +#ifdef _NDEBUG + static char value; + return &value; +#else + return reinterpret_cast (0xc1a); +#endif +} + +/** + * The key of a propget table in another metatable. + */ +inline const void* getPropgetKey () +{ +#ifdef _NDEBUG + static char value; + return &value; +#else + return reinterpret_cast (0x6e7); +#endif +} + +/** + * The key of a propset table in another metatable. + */ +inline const void* getPropsetKey () +{ +#ifdef _NDEBUG + static char value; + return &value; +#else + return reinterpret_cast (0x5e7); +#endif +} + +/** + * The key of a static table in another metatable. + */ +inline const void* getStaticKey () +{ +#ifdef _NDEBUG + static char value; + return &value; +#else + return reinterpret_cast (0x57a); +#endif +} + +/** + * The key of a parent table in another metatable. + */ +inline const void* getParentKey () +{ +#ifdef _NDEBUG + static char value; + return &value; +#else + return reinterpret_cast (0xdad); +#endif +} + +/** + Get the key for the static table in the Lua registry. + The static table holds the static data members, static properties, and + static member functions for a class. +*/ +template +void const* getStaticRegistryKey () +{ + static char value; + return &value; +} + +/** Get the key for the class table in the Lua registry. + The class table holds the data members, properties, and member functions + of a class. Read-only data and properties, and const member functions are + also placed here (to save a lookup in the const table). +*/ +template +void const* getClassRegistryKey () +{ + static char value; + return &value; +} + +/** Get the key for the const table in the Lua registry. + The const table holds read-only data members and properties, and const + member functions of a class. +*/ +template +void const* getConstRegistryKey () +{ + static char value; + return &value; +} + +} // namespace detail + +} // namespace luabridge diff --git a/src/LuaBridge/detail/Config.h b/src/LuaBridge/detail/Config.h new file mode 100644 index 000000000..76b3d4201 --- /dev/null +++ b/src/LuaBridge/detail/Config.h @@ -0,0 +1,10 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2019, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#if !defined (LUABRIDGE_NO_CXX11) && (__cplusplus >= 201103L || (defined (_MSC_VER) && _MSC_VER >= 1900)) +#define LUABRIDGE_CXX11 +#endif diff --git a/src/LuaBridge/detail/Constructor.h b/src/LuaBridge/detail/Constructor.h new file mode 100644 index 000000000..d67ddf2ad --- /dev/null +++ b/src/LuaBridge/detail/Constructor.h @@ -0,0 +1,208 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { +namespace detail { + +/* +* Constructor generators. These templates allow you to call operator new and +* pass the contents of a type/value list to the Constructor. Like the +* function pointer containers, these are only defined up to 8 parameters. +*/ + +/** Constructor generators. + + These templates call operator new with the contents of a type/value + list passed to the Constructor with up to 8 parameters. Two versions + of call() are provided. One performs a regular new, the other performs + a placement new. +*/ +template +struct Constructor {}; + +template +struct Constructor +{ + static T* call (TypeListValues const&) + { + return new T; + } + static T* call (void* mem, TypeListValues const&) + { + return new (mem) T; + } +}; + +template +struct Constructor > +{ + static T* call (const TypeListValues > &tvl) + { + return new T(tvl.hd); + } + static T* call (void* mem, const TypeListValues > &tvl) + { + return new (mem) T(tvl.hd); + } +}; + +template +struct Constructor > > +{ + static T* call (const TypeListValues > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd); + } +}; + +template +struct Constructor > > > +{ + static T* call (const TypeListValues > > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } +}; + +template +struct Constructor > > > > +{ + static T* call (const TypeListValues > > > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); + } +}; + +template +struct Constructor > > > > > +{ + static T* call (const TypeListValues > > > > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd); + } +}; + +template +struct Constructor > > > > > > +{ + static T* call (const TypeListValues > > > > > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > > > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); + } +}; + +template +struct Constructor > > > > > > > +{ + static T* call (const TypeListValues > > > > > > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > > > > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.tl.hd); + } +}; + +template +struct Constructor > > > > > > > > +{ + static T* call (const TypeListValues > > > > > > > > &tvl) + { + return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); + } + static T* call (void* mem, const TypeListValues > > > > > > > > &tvl) + { + return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); + } +}; + +} // namespace detail + +} // namespace luabridge diff --git a/src/LuaBridge/detail/FuncTraits.h b/src/LuaBridge/detail/FuncTraits.h new file mode 100644 index 000000000..d8652f3e1 --- /dev/null +++ b/src/LuaBridge/detail/FuncTraits.h @@ -0,0 +1,945 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2020, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +#ifdef LUABRIDGE_CXX11 +#include +#endif + +namespace luabridge { +namespace detail { + +/** + Since the throw specification is part of a function signature, the FuncTraits + family of templates needs to be specialized for both types. The + LUABRIDGE_THROWSPEC macro controls whether we use the 'throw ()' form, or + 'noexcept' (if C++11 is available) to distinguish the functions. +*/ +#if defined (__APPLE_CPP__) || defined (__APPLE_CC__) || defined (__clang__) || defined (__GNUC__) || \ + (defined (_MSC_VER) && (_MSC_VER >= 1700)) +// Do not define LUABRIDGE_THROWSPEC since the Xcode and gcc compilers do not +// distinguish the throw specification in the function signature. +#define LUABRIDGE_THROWSPEC +#else +// Visual Studio 10 and earlier pay too much mind to useless throw () spec. +// +# define LUABRIDGE_THROWSPEC throw () +#endif + +//============================================================================== +/** + * Traits class for unrolling the type list values into function arguments. + */ +template +struct Caller; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & params) + { + return fn (); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues &) + { + return (obj->*fn) (); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); + } +}; + +template +struct Caller +{ + template + static ReturnType f (Fn& fn, TypeListValues & tvl) + { + return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd); + } + + template + static ReturnType f (T* obj, MemFn& fn, TypeListValues & tvl) + { + return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd, + tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd); + } +}; + +template +ReturnType doCall (Fn& fn, TypeListValues & tvl) +{ + return Caller ::value>::f (fn, tvl); +} + +template +static ReturnType doCall(T* obj, MemFn& fn, TypeListValues & tvl) +{ + return Caller ::value>::f (obj, fn, tvl); +} + +//============================================================================== +/** + Traits for function pointers. + + There are three types of functions: global, non-const member, and const + member. These templates determine the type of function, which class type it + belongs to if it is a class member, the const-ness if it is a member + function, and the type information for the return value and argument list. + + Expansions are provided for functions with up to 8 parameters. This can be + manually extended, or expanded to an arbitrary amount using C++11 features. +*/ +template +struct FuncTraits +{ +}; + +#ifndef LUABRIDGE_CXX11 + +/* Ordinary function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef None Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */ + +#ifdef _M_IX86 // Windows 32bit only + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef None Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (D fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +#endif // _M_IX86 + +/* Non-const member function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef None Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (T* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +/* Const member function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef None Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > Params; + static R call (T const* obj, R (T::*fp) (P1, P2) const, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + typedef D DeclType; + typedef T ClassType; + typedef R ReturnType; + typedef TypeList > > > > > > > Params; + static R call (T const* obj, D fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +#else // ifndef LUABRIDGE_CXX11 + +/* Ordinary function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + using DeclType = R (*) (ParamList...); + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static R call (const DeclType& fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */ + +#ifdef _M_IX86 // Windows 32bit only + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + using DeclType = R (__stdcall *) (ParamList...); + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static R call (const DeclType& fp, TypeListValues & tvl) + { + return doCall (fp, tvl); + } +}; + +#endif // _M_IX86 + +/* Non-const member function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = false; + using DeclType = R (T::*) (ParamList...); + using ClassType = T; + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static R call (ClassType* obj, const DeclType& fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +/* Const member function pointers. */ + +template +struct FuncTraits +{ + static bool const isMemberFunction = true; + static bool const isConstMemberFunction = true; + using DeclType = R (T::*) (ParamList...) const; + using ClassType = T; + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static R call (const ClassType* obj, const DeclType& fp, TypeListValues & tvl) + { + return doCall (obj, fp, tvl); + } +}; + +/* std::function */ + +template +struct FuncTraits > +{ + static bool const isMemberFunction = false; + static bool const isConstMemberFunction = false; + using DeclType = std::function ; + using ReturnType = R; + using Params = typename MakeTypeList ::Result; + + static ReturnType call (DeclType& fn, TypeListValues & tvl) + { + return doCall (fn, tvl); + } +}; + +#endif // ifndef LUABRIDGE_CXX11 + +template +struct Invoke +{ + template + static int run (lua_State* L, Fn& fn) + { + try + { + ArgList args (L); + Stack ::push (L, FuncTraits ::call (fn, args)); + return 1; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } + + template + static int run (lua_State* L, T* object, const MemFn& fn) + { + try + { + ArgList args (L); + Stack ::push (L, FuncTraits ::call (object, fn, args)); + return 1; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } +}; + +template +struct Invoke +{ + template + static int run (lua_State* L, Fn& fn) + { + try + { + ArgList args (L); + FuncTraits ::call (fn, args); + return 0; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } + + template + static int run (lua_State* L, T* object, const MemFn& fn) + { + try + { + ArgList args (L); + FuncTraits ::call (object, fn, args); + return 0; + } + catch (const std::exception& e) + { + return luaL_error (L, e.what ()); + } + } +}; + +} // namespace detail + +} // namespace luabridge diff --git a/src/LuaBridge/detail/Iterator.h b/src/LuaBridge/detail/Iterator.h new file mode 100644 index 000000000..ffab8f43b --- /dev/null +++ b/src/LuaBridge/detail/Iterator.h @@ -0,0 +1,197 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2018, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + + +namespace luabridge { + +/** Allows table iteration. +*/ +class Iterator +{ + lua_State* m_L; + LuaRef m_table; + LuaRef m_key; + LuaRef m_value; + + void next () + { + m_table.push (); + m_key.push (); + if (lua_next (m_L, -2)) + { + m_value.pop (); + m_key.pop (); + } + else + { + m_key = Nil (); + m_value = Nil (); + } + lua_pop (m_L, 1); + } + +public: + explicit Iterator (const LuaRef& table, bool isEnd = false) + : m_L (table.state ()) + , m_table (table) + , m_key (table.state ()) // m_key is nil + , m_value (table.state ()) // m_value is nil + { + if (!isEnd) + { + next (); // get the first (key, value) pair from table + } + } + + /// Return an associated Lua state. + /// + /// @returns A Lua state. + /// + lua_State* state () const + { + return m_L; + } + + /// Dereference the iterator. + /// + /// @returns A key-value pair for a current table entry. + /// + std::pair operator* () const + { + return std::make_pair (m_key, m_value); + } + + /// Return the value referred by the iterator. + /// + /// @returns A value for the current table entry. + /// + LuaRef operator-> () const + { + return m_value; + } + + /// Compare two iterators. + /// + /// @param rhs Another iterator. + /// @returns True if iterators point to the same entry of the same table, + /// false otherwise. + /// + bool operator!= (const Iterator& rhs) const + { + assert (m_L == rhs.m_L); + return !m_table.rawequal (rhs.m_table) || !m_key.rawequal (rhs.m_key); + } + + /// Move the iterator to the next table entry. + /// + /// @returns This iterator. + /// + Iterator& operator++ () + { + if (isNil ()) + { + // if the iterator reaches the end, do nothing + return *this; + } + else + { + next (); + return *this; + } + } + + /// Check if the iterator points after the last table entry. + /// + /// @returns True if there are no more table entries to iterate, + /// false otherwise. + /// + bool isNil () const + { + return m_key.isNil (); + } + + /// Return the key for the current table entry. + /// + /// @returns A reference to the entry key. + /// + LuaRef key () const + { + return m_key; + } + + /// Return the key for the current table entry. + /// + /// @returns A reference to the entry value. + /// + LuaRef value () const + { + return m_value; + } + +private: + // Don't use postfix increment, it is less efficient + Iterator operator++ (int); +}; + +namespace detail { + +class Range +{ + Iterator m_begin; + Iterator m_end; + +public: + Range (const Iterator& begin, const Iterator& end) + : m_begin (begin) + , m_end (end) + { + } + + const Iterator& begin () const { return m_begin; } + const Iterator& end () const { return m_end; } +}; + +} // namespace detail + +/// Return a range for the Lua table reference. +/// +/// @returns A range suitable for range-based for statement. +/// +inline detail::Range pairs (const LuaRef& table) +{ + return detail::Range (Iterator (table, false), Iterator (table, true)); +} + +} // namespace luabridge diff --git a/src/LuaBridge/detail/LuaException.h b/src/LuaBridge/detail/LuaException.h new file mode 100644 index 000000000..836cb852f --- /dev/null +++ b/src/LuaBridge/detail/LuaException.h @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + Copyright 2008, Nigel Atkinson + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { + +class LuaException : public std::exception +{ +private: + lua_State* m_L; + std::string m_what; + +public: + //---------------------------------------------------------------------------- + /** + Construct a LuaException after a lua_pcall(). + */ + LuaException (lua_State* L, int /*code*/) + : m_L (L) + { + whatFromStack (); + } + + //---------------------------------------------------------------------------- + + LuaException (lua_State *L, + char const*, + char const*, + long) + : m_L (L) + { + whatFromStack (); + } + + //---------------------------------------------------------------------------- + + ~LuaException() throw () + { + } + + //---------------------------------------------------------------------------- + + char const* what() const throw () + { + return m_what.c_str(); + } + + //============================================================================ + /** + Throw an exception. + + This centralizes all the exceptions thrown, so that we can set + breakpoints before the stack is unwound, or otherwise customize the + behavior. + */ + template + static void Throw (Exception e) + { + throw e; + } + + //---------------------------------------------------------------------------- + /** + Wrapper for lua_pcall that throws. + */ + static void pcall (lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0) + { + int code = lua_pcall (L, nargs, nresults, msgh); + + if (code != LUABRIDGE_LUA_OK) + Throw (LuaException (L, code)); + } + + //---------------------------------------------------------------------------- + /** + Initializes error handling. Subsequent Lua errors are translated to C++ exceptions. + */ + static void enableExceptions (lua_State* L) + { + lua_atpanic (L, throwAtPanic); + } + +protected: + void whatFromStack () + { + if (lua_gettop (m_L) > 0) + { + char const* s = lua_tostring (m_L, -1); + m_what = s ? s : ""; + } + else + { + // stack is empty + m_what = "missing error"; + } + } + +private: + static int throwAtPanic (lua_State* L) + { + throw LuaException (L, -1); + } +}; + +//---------------------------------------------------------------------------- +/** + Initializes error handling. Subsequent Lua errors are translated to C++ exceptions. +*/ +static void enableExceptions (lua_State* L) +{ + LuaException::enableExceptions (L); +} + +} // namespace luabridge diff --git a/src/LuaBridge/detail/LuaHelpers.h b/src/LuaBridge/detail/LuaHelpers.h new file mode 100644 index 000000000..e336cf2b2 --- /dev/null +++ b/src/LuaBridge/detail/LuaHelpers.h @@ -0,0 +1,151 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { + +// These are for Lua versions prior to 5.2.0. +// +#if LUA_VERSION_NUM < 502 +inline int lua_absindex (lua_State* L, int idx) +{ + if (idx > LUA_REGISTRYINDEX && idx < 0) + return lua_gettop (L) + idx + 1; + else + return idx; +} + +inline void lua_rawgetp (lua_State* L, int idx, void const* p) +{ + idx = lua_absindex (L, idx); + lua_pushlightuserdata (L, const_cast (p)); + lua_rawget (L,idx); +} + +inline void lua_rawsetp (lua_State* L, int idx, void const* p) +{ + idx = lua_absindex (L, idx); + lua_pushlightuserdata (L, const_cast (p)); + // put key behind value + lua_insert (L, -2); + lua_rawset (L, idx); +} + +#define LUA_OPEQ 1 +#define LUA_OPLT 2 +#define LUA_OPLE 3 + +inline int lua_compare (lua_State* L, int idx1, int idx2, int op) +{ + switch (op) + { + case LUA_OPEQ: + return lua_equal (L, idx1, idx2); + break; + + case LUA_OPLT: + return lua_lessthan (L, idx1, idx2); + break; + + case LUA_OPLE: + return lua_equal (L, idx1, idx2) || lua_lessthan (L, idx1, idx2); + break; + + default: + return 0; + }; +} + +inline int get_length (lua_State* L, int idx) +{ + return int (lua_objlen (L, idx)); +} + +#else +inline int get_length (lua_State* L, int idx) +{ + lua_len (L, idx); + int len = int (luaL_checknumber (L, -1)); + lua_pop (L, 1); + return len; +} + +#endif + +#ifndef LUA_OK +# define LUABRIDGE_LUA_OK 0 +#else +# define LUABRIDGE_LUA_OK LUA_OK +#endif + +/** Get a table value, bypassing metamethods. +*/ +inline void rawgetfield (lua_State* L, int index, char const* key) +{ + assert (lua_istable (L, index)); + index = lua_absindex (L, index); + lua_pushstring (L, key); + lua_rawget (L, index); +} + +/** Set a table value, bypassing metamethods. +*/ +inline void rawsetfield (lua_State* L, int index, char const* key) +{ + assert (lua_istable (L, index)); + index = lua_absindex (L, index); + lua_pushstring (L, key); + lua_insert (L, -2); + lua_rawset (L, index); +} + +/** Returns true if the value is a full userdata (not light). +*/ +inline bool isfulluserdata (lua_State* L, int index) +{ + return lua_isuserdata (L, index) && !lua_islightuserdata (L, index); +} + +/** Test lua_State objects for global equality. + + This can determine if two different lua_State objects really point + to the same global state, such as when using coroutines. + + @note This is used for assertions. +*/ +inline bool equalstates (lua_State* L1, lua_State* L2) +{ + return lua_topointer (L1, LUA_REGISTRYINDEX) == + lua_topointer (L2, LUA_REGISTRYINDEX); +} + +} // namespace luabridge diff --git a/src/LuaBridge/detail/LuaRef.h b/src/LuaBridge/detail/LuaRef.h new file mode 100644 index 000000000..e7f41717f --- /dev/null +++ b/src/LuaBridge/detail/LuaRef.h @@ -0,0 +1,1187 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2018, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + Copyright 2008, Nigel Atkinson + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 +#include +#include + +namespace luabridge { + +//------------------------------------------------------------------------------ +/** + Type tag for representing LUA_TNIL. + + Construct one of these using `Nil ()` to represent a Lua nil. This is faster + than creating a reference in the registry to nil. Example: + + LuaRef t (LuaRef::createTable (L)); + ... + t ["k"] = Nil (); // assign nil +*/ +struct Nil +{ +}; + + +//------------------------------------------------------------------------------ +/** + Stack specialization for Nil. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, Nil) + { + lua_pushnil (L); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TTABLE; + } +}; + +/** + * Base class for Lua variables and table item reference classes. + */ +template +class LuaRefBase +{ +protected: + //---------------------------------------------------------------------------- + /** + Pop the Lua stack. + + Pops the specified number of stack items on destruction. We use this + when returning objects, to avoid an explicit temporary variable, since + the destructor executes after the return statement. For example: + + template + U cast (lua_State* L) + { + StackPop p (L, 1); + ... + return U (); // dtor called after this line + } + + @note The `StackPop` object must always be a named local variable. + */ + class StackPop + { + public: + /** Create a StackPop object. + + @param L A Lua state. + @param count The number of stack entries to pop on destruction. + */ + StackPop (lua_State* L, int count) + : m_L (L) + , m_count (count) + { + } + + ~StackPop () + { + lua_pop (m_L, m_count); + } + + private: + lua_State* m_L; + int m_count; + }; + + friend struct Stack ; + + //---------------------------------------------------------------------------- + /** + Type tag for stack construction. + */ + struct FromStack { }; + + LuaRefBase (lua_State* L) + : m_L (L) + { + } + + //---------------------------------------------------------------------------- + /** + Create a reference to this reference. + + @returns An index in the Lua registry. + */ + int createRef () const + { + impl ().push (); + return luaL_ref (m_L, LUA_REGISTRYINDEX); + } + +public: + //---------------------------------------------------------------------------- + /** + Convert to a string using lua_tostring function. + + @returns A string representation of the referred Lua value. + */ + std::string tostring () const + { + lua_getglobal (m_L, "tostring"); + impl ().push (); + lua_call (m_L, 1, 1); + const char* str = lua_tostring (m_L, -1); + lua_pop (m_L, 1); + return str; + } + + //---------------------------------------------------------------------------- + /** + Print a text description of the value to a stream. + This is used for diagnostics. + + @param os An output stream. + */ + void print (std::ostream& os) const + { + switch (type ()) + { + case LUA_TNIL: + os << "nil"; + break; + + case LUA_TNUMBER: + os << cast (); + break; + + case LUA_TBOOLEAN: + os << (cast () ? "true" : "false"); + break; + + case LUA_TSTRING: + os << '"' << cast () << '"'; + break; + + case LUA_TTABLE: + os << "table: " << tostring (); + break; + + case LUA_TFUNCTION: + os << "function: " << tostring (); + break; + + case LUA_TUSERDATA: + os << "userdata: " << tostring (); + break; + + case LUA_TTHREAD: + os << "thread: " << tostring (); + break; + + case LUA_TLIGHTUSERDATA: + os << "lightuserdata: " << tostring (); + break; + + default: + os << "unknown"; + break; + } + } + + //------------------------------------------------------------------------------ + /** + Insert a Lua value or table item reference to a stream. + + @param os An output stream. + @param ref A Lua reference. + @returns The output stream. + */ + friend std::ostream& operator<< (std::ostream& os, LuaRefBase const& ref) + { + ref.print (os); + return os; + } + + //============================================================================ + // + // This group of member functions is mirrored in TableItem + // + + /** Retrieve the lua_State associated with the reference. + + @returns A Lua state. + */ + lua_State* state () const + { + return m_L; + } + + //---------------------------------------------------------------------------- + /** + Place the object onto the Lua stack. + + @param L A Lua state. + */ + void push (lua_State* L) const + { + assert (equalstates (L, m_L)); + (void) L; + impl ().push (); + } + + //---------------------------------------------------------------------------- + /** + Pop the top of Lua stack and assign it to the reference. + + @param L A Lua state. + */ + void pop (lua_State* L) + { + assert (equalstates (L, m_L)); + (void) L; + impl ().pop (); + } + + //---------------------------------------------------------------------------- + /** + Return the Lua type of the referred value. This invokes lua_type(). + + @returns The type of the referred value. + @see lua_type() + */ + /** @{ */ + int type () const + { + impl ().push (); + StackPop p (m_L, 1); + return lua_type (m_L, -1); + } + + // should never happen + // bool isNone () const { return m_ref == LUA_NOREF; } + + /// Indicate whether it is a nil reference. + /// + /// @returns True if this is a nil reference, false otherwice. + /// + bool isNil () const { return type () == LUA_TNIL; } + + /// Indicate whether it is a reference to a boolean. + /// + /// @returns True if it is a reference to a boolean, false otherwice. + /// + bool isBool () const { return type () == LUA_TBOOLEAN; } + + /// Indicate whether it is a reference to a number. + /// + /// @returns True if it is a reference to a number, false otherwise. + /// + bool isNumber () const { return type () == LUA_TNUMBER; } + + /// Indicate whether it is a reference to a string. + /// + /// @returns True if it is a reference to a string, false otherwise. + /// + bool isString () const { return type () == LUA_TSTRING; } + + /// Indicate whether it is a reference to a table. + /// + /// @returns True if it is a reference to a table, false otherwise. + /// + bool isTable () const { return type () == LUA_TTABLE; } + + /// Indicate whether it is a reference to a function. + /// + /// @returns True if it is a reference to a function, false otherwise. + /// + bool isFunction () const { return type () == LUA_TFUNCTION; } + + /// Indicate whether it is a reference to a full userdata. + /// + /// @returns True if it is a reference to a full userdata, false otherwise. + /// + bool isUserdata () const { return type () == LUA_TUSERDATA; } + + /// Indicate whether it is a reference to a Lua thread. + /// + /// @returns True if it is a reference to a Lua thread, false otherwise. + /// + bool isThread () const { return type () == LUA_TTHREAD; } + + /// Indicate whether it is a reference to a light userdata. + /// + /// @returns True if it is a reference to a light userdata, false otherwise. + /// + bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; } + + /** @} */ + + //---------------------------------------------------------------------------- + /** + Perform an explicit conversion to the type T. + + @returns A value of the type T converted from this reference. + */ + template + T cast () const + { + StackPop p (m_L, 1); + impl ().push (); + return Stack ::get (m_L, -1); + } + + //---------------------------------------------------------------------------- + /** + Indicate if this reference is convertible to the type T. + + @returns True if the referred value is convertible to the type T, + false otherwise. + */ + template + bool isInstance () const + { + StackPop p (m_L, 1); + impl ().push (); + return Stack ::isInstance (m_L, -1); + } + + //---------------------------------------------------------------------------- + /** + Type cast operator. + + @returns A value of the type T converted from this reference. + */ + template + operator T () const + { + return cast (); + } + + //---------------------------------------------------------------------------- + /** @{ */ + /** + Compare this reference with a specified value using lua_compare(). + This invokes metamethods. + + @param rhs A value to compare with. + @returns True if the referred value is equal to the specified one. + */ + template + bool operator== (T rhs) const + { + StackPop p (m_L, 2); + impl ().push (); + Stack ::push (m_L, rhs); + return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1; + } + + /** + Compare this reference with a specified value using lua_compare(). + This invokes metamethods. + + @param rhs A value to compare with. + @returns True if the referred value is less than the specified one. + */ + template + bool operator< (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) + { + return lhsType < rhsType; + } + return lua_compare (m_L, -2, -1, LUA_OPLT) == 1; + } + + /** + Compare this reference with a specified value using lua_compare(). + This invokes metamethods. + + @param rhs A value to compare with. + @returns True if the referred value is less than or equal to the specified one. + */ + template + bool operator<= (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) + { + return lhsType <= rhsType; + } + return lua_compare (m_L, -2, -1, LUA_OPLE) == 1; + } + + /** + Compare this reference with a specified value using lua_compare(). + This invokes metamethods. + + @param rhs A value to compare with. + @returns True if the referred value is greater than the specified one. + */ + template + bool operator> (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) + { + return lhsType > rhsType; + } + return lua_compare (m_L, -1, -2, LUA_OPLT) == 1; + } + + /** + Compare this reference with a specified value using lua_compare(). + This invokes metamethods. + + @param rhs A value to compare with. + @returns True if the referred value is greater than or equal to the specified one. + */ + template + bool operator>= (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) + { + return lhsType >= rhsType; + } + return lua_compare (m_L, -1, -2, LUA_OPLE) == 1; + } + + /** + Compare this reference with a specified value using lua_compare(). + This does not invoke metamethods. + + @param rhs A value to compare with. + @returns True if the referred value is equal to the specified one. + */ + template + bool rawequal (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + return lua_rawequal (m_L, -1, -2) == 1; + } + /** @} */ + + //---------------------------------------------------------------------------- + /** + Append a value to a referred table. + If the table is a sequence this will add another element to it. + + @param v A value to append to the table. + */ + template + void append (T v) const + { + impl ().push ();; + Stack ::push (m_L, v); + luaL_ref (m_L, -2); + lua_pop (m_L, 1); + } + + //---------------------------------------------------------------------------- + /** + Return the length of a referred array. + This is identical to applying the Lua # operator. + + @returns The length of the referred array. + */ + int length () const + { + StackPop p (m_L, 1); + impl ().push ();; + return get_length (m_L, -1); + } + + //---------------------------------------------------------------------------- + /** + Call Lua code. + These overloads allow Lua code to be called with up to 8 parameters. + The return value is provided as a LuaRef (which may be LUA_REFNIL). + If an error occurs, a LuaException is thrown. + + @returns A result of the call. + */ + /** @{ */ + LuaRef operator() () const + { + impl ().push ();; + LuaException::pcall (m_L, 0, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1) const + { + impl ().push ();; + Stack ::push (m_L, p1); + LuaException::pcall (m_L, 1, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + LuaException::pcall (m_L, 2, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + LuaException::pcall (m_L, 3, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + LuaException::pcall (m_L, 4, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + LuaException::pcall (m_L, 5, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + LuaException::pcall (m_L, 6, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + Stack ::push (m_L, p7); + LuaException::pcall (m_L, 7, 1); + return LuaRef::fromStack (m_L); + } + + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const + { + impl ().push (); + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + Stack ::push (m_L, p7); + Stack ::push (m_L, p8); + LuaException::pcall (m_L, 8, 1); + return LuaRef::fromStack (m_L); + } + /** @} */ + + //============================================================================ + +protected: + lua_State* m_L; + +private: + const Impl& impl () const + { + return static_cast (*this); + } + + Impl& impl () + { + return static_cast (*this); + } +}; + +//------------------------------------------------------------------------------ +/** + Lightweight reference to a Lua object. + + The reference is maintained for the lifetime of the C++ object. +*/ +class LuaRef : public LuaRefBase +{ + //---------------------------------------------------------------------------- + /** + A proxy for representing table values. + */ + class TableItem : public LuaRefBase + { + friend class LuaRef; + + public: + //-------------------------------------------------------------------------- + /** + Construct a TableItem from a table value. + The table is in the registry, and the key is at the top of the stack. + The key is popped off the stack. + + @param L A lua state. + @param tableRef The index of a table in the Lua registry. + */ + TableItem (lua_State* L, int tableRef) + : LuaRefBase (L) + , m_tableRef (LUA_NOREF) + , m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX)) + { + lua_rawgeti (m_L, LUA_REGISTRYINDEX, tableRef); + m_tableRef = luaL_ref (L, LUA_REGISTRYINDEX); + } + + //-------------------------------------------------------------------------- + /** + Create a TableItem via copy constructor. + It is best to avoid code paths that invoke this, because it creates + an extra temporary Lua reference. Typically this is done by passing + the TableItem parameter as a `const` reference. + + @param other Another Lua table item reference. + */ + TableItem (TableItem const& other) + : LuaRefBase (other.m_L) + , m_tableRef (LUA_NOREF) + , m_keyRef (LUA_NOREF) + { + lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_tableRef); + m_tableRef = luaL_ref (m_L, LUA_REGISTRYINDEX); + + lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef); + m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX); + } + + //-------------------------------------------------------------------------- + /** + Destroy the proxy. + This does not destroy the table value. + */ + ~TableItem () + { + luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef); + luaL_unref (m_L, LUA_REGISTRYINDEX, m_tableRef); + } + + //-------------------------------------------------------------------------- + /** + Assign a new value to this table key. + This may invoke metamethods. + + @tparam T The type of a value to assing. + @param v A value to assign. + @returns This reference. + */ + template + TableItem& operator= (T v) + { + StackPop p (m_L, 1); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); + Stack ::push (m_L, v); + lua_settable (m_L, -3); + return *this; + } + + //-------------------------------------------------------------------------- + /** + Assign a new value to this table key. + The assignment is raw, no metamethods are invoked. + + @tparam T The type of a value to assing. + @param v A value to assign. + @returns This reference. + */ + template + TableItem& rawset (T v) + { + StackPop p (m_L, 1); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); + Stack ::push (m_L, v); + lua_rawset (m_L, -3); + return *this; + } + + //-------------------------------------------------------------------------- + /** + Push the value onto the Lua stack. + */ + using LuaRefBase::push; + + void push () const + { + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); + lua_gettable (m_L, -2); + lua_remove (m_L, -2); // remove the table + } + + //-------------------------------------------------------------------------- + /** + Access a table value using a key. + This invokes metamethods. + + @tparam T The type of a key. + @param key A key value. + @returns A Lua table item reference. + */ + template + TableItem operator[] (T key) const + { + return LuaRef (*this) [key]; + } + + //-------------------------------------------------------------------------- + /** + Access a table value using a key. + The operation is raw, metamethods are not invoked. The result is + passed by value and may not be modified. + + @tparam T The type of a key. + @param key A key value. + @returns A Lua value reference. + */ + template + LuaRef rawget (T key) const + { + return LuaRef (*this).rawget (key); + } + + private: + int m_tableRef; + int m_keyRef; + }; + + friend struct Stack ; + friend struct Stack ; + + //---------------------------------------------------------------------------- + /** + Create a reference to an object at the top of the Lua stack and pop it. + This constructor is private and not invoked directly. + Instead, use the `fromStack` function. + + @param L A Lua state. + @note The object is popped. + */ + LuaRef (lua_State* L, FromStack) + : LuaRefBase (L) + , m_ref (luaL_ref (m_L, LUA_REGISTRYINDEX)) + { + } + + //---------------------------------------------------------------------------- + /** + Create a reference to an object on the Lua stack. + This constructor is private and not invoked directly. + Instead, use the `fromStack` function. + + @param L A Lua state. + @param index The index of the value on the Lua stack. + @note The object is not popped. + */ + LuaRef (lua_State* L, int index, FromStack) + : LuaRefBase (L) + , m_ref (LUA_NOREF) + { + lua_pushvalue (m_L, index); + m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); + } + + +public: + //---------------------------------------------------------------------------- + /** + Create a nil reference. + The Lua reference may be assigned later. + + @param L A Lua state. + */ + LuaRef (lua_State* L) + : LuaRefBase (L) + , m_ref (LUA_NOREF) + { + } + + //---------------------------------------------------------------------------- + /** + Push a value onto a Lua stack and return a reference to it. + + @param L A Lua state. + @param v A value to push. + */ + template + LuaRef (lua_State* L, T v) + : LuaRefBase (L) + , m_ref (LUA_NOREF) + { + Stack ::push (m_L, v); + m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); + } + + //---------------------------------------------------------------------------- + /** + Create a reference to a table item. + + @param v A table item reference. + */ + LuaRef (TableItem const& v) + : LuaRefBase (v.state ()) + , m_ref (v.createRef ()) + { + } + + //---------------------------------------------------------------------------- + /** + Create a new reference to an existing Lua value. + + @param other An existing reference. + */ + LuaRef (LuaRef const& other) + : LuaRefBase (other.m_L) + , m_ref (other.createRef ()) + { + } + + //---------------------------------------------------------------------------- + /** + Destroy a reference. + + The corresponding Lua registry reference will be released. + + @note If the state refers to a thread, it is the responsibility of the + caller to ensure that the thread still exists when the LuaRef + is destroyed. + */ + ~LuaRef () + { + luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); + } + + //---------------------------------------------------------------------------- + /** + Return a reference to a top Lua stack item. + The stack item is not popped. + + @param L A Lua state. + @returns A reference to a value on the top of a Lua stack. + */ + static LuaRef fromStack (lua_State* L) + { + return LuaRef (L, FromStack ()); + } + + //---------------------------------------------------------------------------- + /** + Return a reference to a Lua stack item with a specified index. + The stack item is not removed. + + @param L A Lua state. + @param index An index in the Lua stack. + @returns A reference to a value in a Lua stack. + */ + static LuaRef fromStack (lua_State* L, int index) + { + lua_pushvalue (L, index); + return LuaRef (L, FromStack ()); + } + + //---------------------------------------------------------------------------- + /** + Create a new empty table on the top of a Lua stack + and return a reference to it. + + @param L A Lua state. + @returns A reference to the newly created table. + @see luabridge::newTable() + */ + static LuaRef newTable (lua_State* L) + { + lua_newtable (L); + return LuaRef (L, FromStack ()); + } + + //---------------------------------------------------------------------------- + /** + Return a reference to a named global Lua variable. + + @param L A Lua state. + @param name The name of a global variable. + @returns A reference to the Lua variable. + @see luabridge::getGlobal() + */ + static LuaRef getGlobal (lua_State *L, char const* name) + { + lua_getglobal (L, name); + return LuaRef (L, FromStack ()); + } + + //---------------------------------------------------------------------------- + /** + Assign another LuaRef to this LuaRef. + + @param rhs A reference to assign from. + @returns This reference. + */ + LuaRef& operator= (LuaRef const& rhs) + { + LuaRef ref (rhs); + swap (ref); + return *this; + } + + //---------------------------------------------------------------------------- + /** + Assign a table item reference. + + @param rhs A table item reference. + @returns This reference. + */ + LuaRef& operator= (LuaRef::TableItem const& rhs) + { + LuaRef ref (rhs); + swap (ref); + return *this; + } + + //---------------------------------------------------------------------------- + /** + Assign nil to this reference. + + @returns This reference. + */ + LuaRef& operator= (Nil const&) + { + LuaRef ref (m_L); + swap (ref); + return *this; + } + + //---------------------------------------------------------------------------- + /** + Assign a different value to this reference. + + @param rhs A value to assign. + @returns This reference. + */ + template + LuaRef& operator= (T rhs) + { + LuaRef ref (m_L, rhs); + swap (ref); + return *this; + } + + //---------------------------------------------------------------------------- + /** + Place the object onto the Lua stack. + */ + using LuaRefBase::push; + + void push () const + { + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_ref); + } + + //---------------------------------------------------------------------------- + /** + Pop the top of Lua stack and assign the ref to m_ref + */ + void pop () + { + luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); + m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); + } + + //---------------------------------------------------------------------------- + /** + Access a table value using a key. + This invokes metamethods. + + @param key A key in the table. + @returns A reference to the table item. + */ + template + TableItem operator[] (T key) const + { + Stack ::push (m_L, key); + return TableItem (m_L, m_ref); + } + + //-------------------------------------------------------------------------- + /** + Access a table value using a key. + The operation is raw, metamethods are not invoked. The result is + passed by value and may not be modified. + + @param key A key in the table. + @returns A reference to the table item. + */ + template + LuaRef rawget (T key) const + { + StackPop (m_L, 1); + push (m_L); + Stack ::push (m_L, key); + lua_rawget (m_L, -2); + return LuaRef (m_L, FromStack ()); + } + +private: + void swap (LuaRef& other) + { + std::swap (m_L, other.m_L); + std::swap (m_ref, other.m_ref); + } + + int m_ref; +}; + +//------------------------------------------------------------------------------ +/** + * Stack specialization for `LuaRef`. + */ +template <> +struct Stack +{ + // The value is const& to prevent a copy construction. + // + static void push (lua_State* L, LuaRef const& v) + { + v.push (L); + } + + static LuaRef get (lua_State* L, int index) + { + return LuaRef::fromStack (L, index); + } +}; + +//------------------------------------------------------------------------------ +/** + * Stack specialization for `TableItem`. + */ +template <> +struct Stack +{ + // The value is const& to prevent a copy construction. + // + static void push (lua_State* L, LuaRef::TableItem const& v) + { + v.push (L); + } +}; + +//------------------------------------------------------------------------------ +/** + Create a reference to a new, empty table. + + This is a syntactic abbreviation for LuaRef::newTable (). +*/ +inline LuaRef newTable (lua_State* L) +{ + return LuaRef::newTable (L); +} + +//------------------------------------------------------------------------------ +/** + Create a reference to a value in the global table. + + This is a syntactic abbreviation for LuaRef::getGlobal (). +*/ +inline LuaRef getGlobal (lua_State *L, char const* name) +{ + return LuaRef::getGlobal (L, name); +} + +//------------------------------------------------------------------------------ + +// more C++-like cast syntax +// +template +T LuaRef_cast (LuaRef const& lr) +{ + return lr.cast (); +} + +} // namespace luabridge diff --git a/src/LuaBridge/detail/Namespace.h b/src/LuaBridge/detail/Namespace.h new file mode 100644 index 000000000..6694a8fed --- /dev/null +++ b/src/LuaBridge/detail/Namespace.h @@ -0,0 +1,1405 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 +#include + +#include +#include + +namespace luabridge { + +namespace detail { + +/** + * Base for class and namespace registration. + * Maintains Lua stack in the proper state. + * Once beginNamespace, beginClass or deriveClass is called the parent + * object upon its destruction may no longer clear the Lua stack. + * Then endNamespace or endClass is called, a new parent is created + * and the child transfers the responsibility for clearing stack to it. + * So there can be maximum one "active" registrar object. + */ +class Registrar +{ +protected: + lua_State* const L; + int mutable m_stackSize; + + Registrar (lua_State* L) + : L (L) + , m_stackSize (0) + { + } + + Registrar (const Registrar& rhs) + : L (rhs.L) + , m_stackSize (rhs.m_stackSize) + { + rhs.m_stackSize = 0; + } + +#ifndef _MSC_VER + // MS compiler thinks it's the 2nd copy ctor + Registrar(Registrar& rhs) + : L (rhs.L) + , m_stackSize (rhs.m_stackSize) + { + rhs.m_stackSize = 0; + } +#endif // ifndef _MSC_VER + + Registrar& operator= (const Registrar& rhs) + { + Registrar tmp (rhs); + std::swap (m_stackSize, tmp.m_stackSize); + return *this; + } + + ~Registrar () + { + if (m_stackSize > 0) + { + assert (m_stackSize <= lua_gettop (L)); + lua_pop (L, m_stackSize); + } + } + + void assertIsActive () const + { + if (m_stackSize == 0) + { + throw std::logic_error ("Unable to continue registration"); + } + } +}; + +} // namespace detail + +/** Provides C++ to Lua registration capabilities. + + This class is not instantiated directly, call `getGlobalNamespace` to start + the registration process. +*/ +class Namespace : public detail::Registrar +{ + typedef detail::CFunc CFunc; + + //============================================================================ +#if 0 + /** + Error reporting. + + VF: This function looks handy, why aren't we using it? + */ + static int luaError (lua_State* L, std::string message) + { + assert (lua_isstring (L, lua_upvalueindex (1))); + std::string s; + + // Get information on the caller's caller to format the message, + // so the error appears to originate from the Lua source. + lua_Debug ar; + int result = lua_getstack (L, 2, &ar); + if (result != 0) + { + lua_getinfo (L, "Sl", &ar); + s = ar.short_src; + if (ar.currentline != -1) + { + // poor mans int to string to avoid . + lua_pushnumber (L, ar.currentline); + s = s + ":" + lua_tostring (L, -1) + ": "; + lua_pop (L, 1); + } + } + + s = s + message; + + return luaL_error (L, s.c_str ()); + } +#endif + + /** + Factored base to reduce template instantiations. + */ + class ClassBase : public detail::Registrar + { + public: + explicit ClassBase (Namespace& parent) + : Registrar (parent) + { + } + + using Registrar::operator=; + + protected: + //-------------------------------------------------------------------------- + /** + Create the const table. + */ + void createConstTable (const char* name, bool trueConst = true) + { + std::string type_name = std::string (trueConst ? "const " : "") + name; + + // Stack: namespace table (ns) + lua_newtable (L); // Stack: ns, const table (co) + lua_pushvalue (L, -1); // Stack: ns, co, co + lua_setmetatable (L, -2); // co.__metatable = co. Stack: ns, co + + lua_pushstring (L, type_name.c_str ()); + lua_rawsetp (L, -2, detail::getTypeKey ()); // co [typeKey] = name. Stack: ns, co + + lua_pushcfunction (L, &CFunc::indexMetaMethod); + rawsetfield (L, -2, "__index"); + + lua_pushcfunction (L, &CFunc::newindexObjectMetaMethod); + rawsetfield (L, -2, "__newindex"); + + lua_newtable (L); + lua_rawsetp (L, -2, detail::getPropgetKey ()); + + if (Security::hideMetatables ()) + { + lua_pushnil (L); + rawsetfield (L, -2, "__metatable"); + } + } + + //-------------------------------------------------------------------------- + /** + Create the class table. + + The Lua stack should have the const table on top. + */ + void createClassTable (char const* name) + { + // Stack: namespace table (ns), const table (co) + + // Class table is the same as const table except the propset table + createConstTable (name, false); // Stack: ns, co, cl + + lua_newtable (L); // Stack: ns, co, cl, propset table (ps) + lua_rawsetp (L, -2, detail::getPropsetKey ()); // cl [propsetKey] = ps. Stack: ns, co, cl + + lua_pushvalue (L, -2); // Stack: ns, co, cl, co + lua_rawsetp(L, -2, detail::getConstKey ()); // cl [constKey] = co. Stack: ns, co, cl + + lua_pushvalue (L, -1); // Stack: ns, co, cl, cl + lua_rawsetp (L, -3, detail::getClassKey ()); // co [classKey] = cl. Stack: ns, co, cl + } + + //-------------------------------------------------------------------------- + /** + Create the static table. + */ + void createStaticTable (char const* name) + { + // Stack: namespace table (ns), const table (co), class table (cl) + lua_newtable (L); // Stack: ns, co, cl, visible static table (vst) + lua_newtable (L); // Stack: ns, co, cl, st, static metatable (st) + lua_pushvalue (L, -1); // Stack: ns, co, cl, vst, st, st + lua_setmetatable (L, -3); // st.__metatable = mt. Stack: ns, co, cl, vst, st + lua_insert (L, -2); // Stack: ns, co, cl, st, vst + rawsetfield (L, -5, name); // ns [name] = vst. Stack: ns, co, cl, st + +#if 0 + lua_pushlightuserdata (L, this); + lua_pushcclosure (L, &tostringMetaMethod, 1); + rawsetfield (L, -2, "__tostring"); +#endif + lua_pushcfunction (L, &CFunc::indexMetaMethod); + rawsetfield (L, -2, "__index"); + + lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod); + rawsetfield (L, -2, "__newindex"); + + lua_newtable (L); // Stack: ns, co, cl, st, proget table (pg) + lua_rawsetp (L, -2, detail::getPropgetKey ()); // st [propgetKey] = pg. Stack: ns, co, cl, st + + lua_newtable (L); // Stack: ns, co, cl, st, propset table (ps) + lua_rawsetp (L, -2, detail::getPropsetKey ()); // st [propsetKey] = pg. Stack: ns, co, cl, st + + lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp(L, -2, detail::getClassKey()); // st [classKey] = cl. Stack: ns, co, cl, st + + if (Security::hideMetatables ()) + { + lua_pushnil (L); + rawsetfield (L, -2, "__metatable"); + } + } + + //========================================================================== + /** + lua_CFunction to construct a class object wrapped in a container. + */ + template + static int ctorContainerProxy (lua_State* L) + { + typedef typename ContainerTraits ::Type T; + detail::ArgList args (L); + T* const p = detail::Constructor ::call (args); + detail::UserdataSharedHelper ::push (L, p); + return 1; + } + + //-------------------------------------------------------------------------- + /** + lua_CFunction to construct a class object in-place in the userdata. + */ + template + static int ctorPlacementProxy (lua_State* L) + { + detail::ArgList args (L); + detail::UserdataValue * value = detail::UserdataValue ::place (L); + detail::Constructor ::call (value->getObject (), args); + value->commit (); + return 1; + } + + void assertStackState () const + { + // Stack: const table (co), class table (cl), static table (st) + assert (lua_istable (L, -3)); + assert (lua_istable (L, -2)); + assert (lua_istable (L, -1)); + } + }; + + //============================================================================ + // + // Class + // + //============================================================================ + /** + Provides a class registration in a lua_State. + + After construction the Lua stack holds these objects: + -1 static table + -2 class table + -3 const table + -4 enclosing namespace table + */ + template + class Class : public ClassBase + { + typedef detail::CFunc CFunc; + + public: + //========================================================================== + /** + Register a new class or add to an existing class registration. + + @param name The new class name. + @param parent A parent namespace object. + */ + Class (char const* name, Namespace& parent) + : ClassBase (parent) + { + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + rawgetfield (L, -1, name); // Stack: ns, static table (st) | nil + + if (lua_isnil (L, -1)) // Stack: ns, nil + { + lua_pop (L, 1); // Stack: ns + + createConstTable (name); // Stack: ns, const table (co) + lua_pushcfunction (L, &CFunc::gcMetaMethod ); // Stack: ns, co, function + rawsetfield (L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co + ++m_stackSize; + + createClassTable (name); // Stack: ns, co, class table (cl) + lua_pushcfunction (L, &CFunc::gcMetaMethod ); // Stack: ns, co, cl, function + rawsetfield (L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl + ++m_stackSize; + + createStaticTable (name); // Stack: ns, co, cl, st + ++m_stackSize; + + // Map T back to its tables. + lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp (L, LUA_REGISTRYINDEX, detail::getStaticRegistryKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp (L, LUA_REGISTRYINDEX, detail::getClassRegistryKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co + lua_rawsetp (L, LUA_REGISTRYINDEX, detail::getConstRegistryKey ()); // Stack: ns, co, cl, st + } + else + { + assert (lua_istable (L, -1)); // Stack: ns, st + ++m_stackSize; + + // Map T back from its stored tables + + lua_rawgetp (L, LUA_REGISTRYINDEX, detail::getConstRegistryKey ()); // Stack: ns, st, co + lua_insert (L, -2); // Stack: ns, co, st + ++m_stackSize; + + lua_rawgetp (L, LUA_REGISTRYINDEX, detail::getClassRegistryKey ()); // Stack: ns, co, st, cl + lua_insert (L, -2); // Stack: ns, co, cl, st + ++m_stackSize; + } + } + + //========================================================================== + /** + Derive a new class. + + @param name The class name. + @param parent A parent namespace object. + @param staticKey + */ + Class (char const* name, Namespace& parent, void const* const staticKey) + : ClassBase (parent) + { + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + createConstTable (name); // Stack: ns, const table (co) + lua_pushcfunction (L, &CFunc::gcMetaMethod ); // Stack: ns, co, function + rawsetfield (L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co + ++m_stackSize; + + createClassTable (name); // Stack: ns, co, class table (cl) + lua_pushcfunction (L, &CFunc::gcMetaMethod ); // Stack: ns, co, cl, function + rawsetfield (L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl + ++m_stackSize; + + createStaticTable (name); // Stack: ns, co, cl, st + ++m_stackSize; + + lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey); // Stack: ns, co, cl, st, parent st (pst) | nil + if (lua_isnil (L, -1)) // Stack: ns, co, cl, st, nil + { + ++m_stackSize; + throw std::runtime_error ("Base class is not registered"); + } + + assert (lua_istable (L, -1)); // Stack: ns, co, cl, st, pst + + lua_rawgetp (L, -1, detail::getClassKey ()); // Stack: ns, co, cl, st, pst, parent cl (pcl) + assert (lua_istable (L, -1)); + + lua_rawgetp (L, -1, detail::getConstKey ()); // Stack: ns, co, cl, st, pst, pcl, parent co (pco) + assert (lua_istable (L, -1)); + + lua_rawsetp (L, -6, detail::getParentKey ()); // co [parentKey] = pco. Stack: ns, co, cl, st, pst, pcl + lua_rawsetp (L, -4, detail::getParentKey ()); // cl [parentKey] = pcl. Stack: ns, co, cl, st, pst + lua_rawsetp (L, -2, detail::getParentKey ()); // st [parentKey] = pst. Stack: ns, co, cl, st + + lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp (L, LUA_REGISTRYINDEX, detail::getStaticRegistryKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp (L, LUA_REGISTRYINDEX, detail::getClassRegistryKey ()); // Stack: ns, co, cl, st + lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co + lua_rawsetp (L, LUA_REGISTRYINDEX, detail::getConstRegistryKey ()); // Stack: ns, co, cl, st + } + + //-------------------------------------------------------------------------- + /** + Continue registration in the enclosing namespace. + + @returns A parent registration object. + */ + Namespace endClass () + { + assert (m_stackSize > 3); + m_stackSize -= 3; + lua_pop (L, 3); + return Namespace (*this); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a static property. + + @tparam U The type of the property. + @param name The property name. + @param value A property value pointer. + @param isWritable True for a read-write, false for read-only property. + @returns This class registration object. + */ + template + Class & addStaticProperty (char const* name, U* value, bool isWritable = true) + { + return addStaticData (name, value, isWritable); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a static property. + + @tparam U The type of the property. + @param name The property name. + @param value A property value pointer. + @param isWritable True for a read-write, false for read-only property. + @returns This class registration object. + */ + template + Class & addStaticData (char const* name, U* value, bool isWritable = true) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata (L, value); // Stack: co, cl, st, pointer + lua_pushcclosure (L, &CFunc::getVariable , 1); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -2); // Stack: co, cl, st + + if (isWritable) + { + lua_pushlightuserdata (L, value); // Stack: co, cl, st, ps, pointer + lua_pushcclosure (L, &CFunc::setVariable , 1); // Stack: co, cl, st, ps, setter + } + else + { + lua_pushstring (L, name); // Stack: co, cl, st, name + lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn + } + CFunc::addSetter (L, name, -2); // Stack: co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + /// Add or replace a static property member. + /// + /// @tparam U The type of the property. + /// @param name The property name. + /// @param get A property getter function pointer. + /// @param set A property setter function pointer, optional, nullable. + /// Omit or pass nullptr for a read-only property. + /// @returns This class registration object. + /// + template + Class & addStaticProperty (char const* name, U (*get) (), void (*set) (U) = 0) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata (L, reinterpret_cast (get)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -2); // Stack: co, cl, st + + if (set != 0) + { + lua_pushlightuserdata (L, reinterpret_cast (set)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: co, cl, st, setter + } + else + { + lua_pushstring (L, name); // Stack: co, cl, st, ps, name + lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn + } + CFunc::addSetter (L, name, -2); // Stack: co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a static member function. + */ + template + Class & addStaticFunction (char const* name, FP const fp) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata (L, reinterpret_cast (fp)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // co, cl, st, function + rawsetfield (L, -2, name); // co, cl, st + + return *this; + } + +#ifdef LUABRIDGE_CXX11 + + //-------------------------------------------------------------------------- + /** + Add or replace a static member function by std::function. + */ + template + Class & addStaticFunction (char const* name, std::function function) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + using FnType = decltype (function); + new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud) + lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt) + lua_pushcfunction (L, &CFunc::gcMetaMethodAny ); // Stack: co, cl, st, ud, mt, gc function + rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt + lua_setmetatable (L, -2); // Stack: co, cl, st, ud + lua_pushcclosure (L, &CFunc::CallProxyFunctor ::f, 1); // Stack: co, cl, st, function + rawsetfield (L, -2, name); // Stack: co, cl, st + + return *this; + } + +#endif // LUABRIDGE_CXX11 + + //-------------------------------------------------------------------------- + /** + Add or replace a lua_CFunction. + + @param name The name of the function. + @param fp A C-function pointer. + @returns This class registration object. + */ + Class & addStaticFunction (char const* name, int (*const fp) (lua_State*)) + { + return addStaticCFunction (name, fp); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a lua_CFunction. + */ + Class & addStaticCFunction (char const* name, int (*const fp) (lua_State*)) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushcfunction (L, fp); // co, cl, st, function + rawsetfield (L, -2, name); // co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + template + Class & addProperty (char const* name, U T::* mp, bool isWritable = true) + { + return addData (name, mp, isWritable); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a data member. + */ + template + Class & addData (char const* name, U T::* mp, bool isWritable = true) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + typedef const U T::*mp_t; + new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr + lua_pushcclosure (L, &CFunc::getProperty , 1); // Stack: co, cl, st, getter + lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter + CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -3); // Stack: co, cl, st + + if (isWritable) + { + new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr + lua_pushcclosure (L, &CFunc::setProperty , 1); // Stack: co, cl, st, setter + CFunc::addSetter (L, name, -3); // Stack: co, cl, st + } + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a property member. + */ + template + Class & addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS) = 0) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + typedef TG (T::*get_t) () const; + new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr + lua_pushcclosure (L, &CFunc::CallConstMember ::f, 1); // Stack: co, cl, st, getter + lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter + CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -3); // Stack: co, cl, st + + if (set != 0) + { + typedef void (T::* set_t) (TS); + new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::CallMember ::f, 1); // Stack: co, cl, st, setter + CFunc::addSetter (L, name, -3); // Stack: co, cl, st + } + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a property member. + */ + template + Class & addProperty (char const* name, TG (T::* get) (lua_State*) const, void (T::* set) (TS, lua_State*) = 0) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + typedef TG (T::*get_t) (lua_State*) const; + new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr + lua_pushcclosure (L, &CFunc::CallConstMember ::f, 1); // Stack: co, cl, st, getter + lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter + CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -3); // Stack: co, cl, st + + if (set != 0) + { + typedef void (T::* set_t) (TS, lua_State*); + new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::CallMember ::f, 1); // Stack: co, cl, st, setter + CFunc::addSetter (L, name, -3); // Stack: co, cl, st + } + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a property member, by proxy. + + When a class is closed for modification and does not provide (or cannot + provide) the function signatures necessary to implement get or set for + a property, this will allow non-member functions act as proxies. + + Both the get and the set functions require a T const* and T* in the first + argument respectively. + */ + template + Class & addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS) = 0) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata (L, reinterpret_cast (get)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: co, cl, st, getter + lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter + CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -3); // Stack: co, cl, st + + if (set != 0) + { + lua_pushlightuserdata (L, reinterpret_cast (set)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: co, cl, st, setter + CFunc::addSetter (L, name, -3); // Stack: co, cl, st + } + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a property member, by proxy C-function. + + When a class is closed for modification and does not provide (or cannot + provide) the function signatures necessary to implement get or set for + a property, this will allow non-member functions act as proxies. + + The object userdata ('this') value is at the index 1. + The new value for set function is at the index 2. + */ + Class & addProperty (char const* name, int (*get) (lua_State*), int (*set) (lua_State*) = 0) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushcfunction (L, get); + lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter + CFunc::addGetter (L, name, -5); // Stack: co, cl, st,, getter + CFunc::addGetter (L, name, -3); // Stack: co, cl, st, + + if (set != 0) + { + lua_pushcfunction (L, set); + CFunc::addSetter (L, name, -3); // Stack: co, cl, st, + } + + return *this; + } + +#ifdef LUABRIDGE_CXX11 + template + Class & addProperty (char const* name, + std::function get, + std::function set = nullptr) + { + using GetType = decltype (get); + new (lua_newuserdata (L, sizeof (get))) GetType (std::move (get)); // Stack: co, cl, st, function userdata (ud) + lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt) + lua_pushcfunction (L, &CFunc::gcMetaMethodAny ); // Stack: co, cl, st, ud, mt, gc function + rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt + lua_setmetatable (L, -2); // Stack: co, cl, st, ud + lua_pushcclosure (L, &CFunc::CallProxyFunctor ::f, 1); // Stack: co, cl, st, getter + lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter + CFunc::addGetter (L, name, -4); // Stack: co, cl, st, getter + CFunc::addGetter (L, name, -4); // Stack: co, cl, st + + if (set != nullptr) + { + using SetType = decltype (set); + new (lua_newuserdata (L, sizeof (set))) SetType (std::move (set)); // Stack: co, cl, st, function userdata (ud) + lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt) + lua_pushcfunction (L, &CFunc::gcMetaMethodAny ); // Stack: co, cl, st, ud, mt, gc function + rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt + lua_setmetatable (L, -2); // Stack: co, cl, st, ud + lua_pushcclosure (L, &CFunc::CallProxyFunctor ::f, 1); // Stack: co, cl, st, setter + CFunc::addSetter (L, name, -3); // Stack: co, cl, st + } + + return *this; + } + +#endif // LUABRIDGE_CXX11 + +#ifndef LUABRIDGE_CXX11 + + //-------------------------------------------------------------------------- + /** + Add or replace a member function. + */ + template + Class & addFunction (char const* name, MemFn mf) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + static const std::string GC = "__gc"; + if (name == GC) + { + throw std::logic_error (GC + " metamethod registration is forbidden"); + } + CFunc::CallMemberFunctionHelper ::isConstMemberFunction>::add (L, name, mf); + return *this; + } + +#else // ifndef LUABRIDGE_CXX11 + + //-------------------------------------------------------------------------- + /** + Add or replace a member function by std::function. + */ + template + Class & addFunction (char const* name, std::function function) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + using FnType = decltype (function); + new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud) + lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt) + lua_pushcfunction (L, &CFunc::gcMetaMethodAny ); // Stack: co, cl, st, ud, mt, gc function + rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt + lua_setmetatable (L, -2); // Stack: co, cl, st, ud + lua_pushcclosure (L, &CFunc::CallProxyFunctor ::f, 1); // Stack: co, cl, st, function + rawsetfield (L, -3, name); // Stack: co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a const member function by std::function. + */ + template + Class & addFunction (char const* name, std::function function) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + using FnType = decltype (function); + new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud) + lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt) + lua_pushcfunction (L, &CFunc::gcMetaMethodAny ); // Stack: co, cl, st, ud, mt, gc function + rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt + lua_setmetatable (L, -2); // Stack: co, cl, st, ud + lua_pushcclosure (L, &CFunc::CallProxyFunctor ::f, 1); // Stack: co, cl, st, function + lua_pushvalue (L, -1); // Stack: co, cl, st, function, function + rawsetfield (L, -4, name); // Stack: co, cl, st, function + rawsetfield (L, -4, name); // Stack: co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a member function. + */ + template + Class & addFunction (char const* name, ReturnType (T::* mf) (Params...)) + { + using MemFn = ReturnType (T::*) (Params...); + + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + static const std::string GC = "__gc"; + if (name == GC) + { + throw std::logic_error (GC + " metamethod registration is forbidden"); + } + CFunc::CallMemberFunctionHelper ::add (L, name, mf); + return *this; + } + + template + Class & addFunction (char const* name, ReturnType (T::* mf) (Params...) const) + { + using MemFn = ReturnType (T::*) (Params...) const; + + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + static const std::string GC = "__gc"; + if (name == GC) + { + throw std::logic_error (GC + " metamethod registration is forbidden"); + } + CFunc::CallMemberFunctionHelper ::add (L, name, mf); + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a proxy function. + */ + template + Class & addFunction (char const* name, ReturnType (*proxyFn) (T* object, Params...)) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + static const std::string GC = "__gc"; + if (name == GC) + { + throw std::logic_error (GC + " metamethod registration is forbidden"); + } + using FnType = decltype (proxyFn); + lua_pushlightuserdata (L, reinterpret_cast (proxyFn)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::CallProxyFunction ::f, 1); // Stack: co, cl, st, function + rawsetfield (L, -3, name); // Stack: co, cl, st + return *this; + } + + template + Class & addFunction (char const* name, ReturnType (*proxyFn) (const T* object, Params...)) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + static const std::string GC = "__gc"; + if (name == GC) + { + throw std::logic_error (GC + " metamethod registration is forbidden"); + } + using FnType = decltype (proxyFn); + lua_pushlightuserdata (L, reinterpret_cast (proxyFn)); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::CallProxyFunction ::f, 1); // Stack: co, cl, st, function + lua_pushvalue (L, -1); // Stack: co, cl, st, function, function + rawsetfield (L, -4, name); // Stack: co, cl, st, function + rawsetfield (L, -4, name); // Stack: co, cl, st + return *this; + } + +#endif + + //-------------------------------------------------------------------------- + /** + Add or replace a member lua_CFunction. + */ + Class & addFunction (char const* name, int (T::*mfp) (lua_State*)) + { + return addCFunction (name, mfp); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a member lua_CFunction. + */ + Class & addCFunction (char const* name, int (T::*mfp) (lua_State*)) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + typedef int (T::*MFP) (lua_State*); + new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); // Stack: co, cl, st, function ptr + lua_pushcclosure (L, &CFunc::CallMemberCFunction ::f, 1); // Stack: co, cl, st, function + rawsetfield (L, -3, name); // Stack: co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a const member lua_CFunction. + */ + Class & addFunction (char const* name, int (T::*mfp) (lua_State*) const) + { + return addCFunction (name, mfp); + } + + //-------------------------------------------------------------------------- + /** + Add or replace a const member lua_CFunction. + */ + Class & addCFunction (char const* name, int (T::*mfp) (lua_State*) const) + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + typedef int (T::*MFP) (lua_State*) const; + new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); + lua_pushcclosure (L, &CFunc::CallConstMemberCFunction ::f, 1); + lua_pushvalue (L, -1); // Stack: co, cl, st, function, function + rawsetfield (L, -4, name); // Stack: co, cl, st, function + rawsetfield (L, -4, name); // Stack: co, cl, st + + return *this; + } + + //-------------------------------------------------------------------------- + /** + Add or replace a primary Constructor. + + The primary Constructor is invoked when calling the class type table + like a function. + + The template parameter should be a function pointer type that matches + the desired Constructor (since you can't take the address of a Constructor + and pass it as an argument). + */ + template + Class & addConstructor () + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushcclosure (L, &ctorContainerProxy ::Params, C>, 0); + rawsetfield (L, -2, "__call"); + + return *this; + } + + template + Class & addConstructor () + { + assertStackState (); // Stack: const table (co), class table (cl), static table (st) + + lua_pushcclosure (L, &ctorPlacementProxy ::Params, T>, 0); + rawsetfield (L, -2, "__call"); + + return *this; + } + }; + +private: + //---------------------------------------------------------------------------- + /** + Open the global namespace for registrations. + + @param L A Lua state. + */ + explicit Namespace (lua_State* L) + : Registrar (L) + { + lua_getglobal (L, "_G"); + ++m_stackSize; + } + + //---------------------------------------------------------------------------- + /** + Open a namespace for registrations. + The namespace is created if it doesn't already exist. + + @param name The namespace name. + @param parent The parent namespace object. + @pre The parent namespace is at the top of the Lua stack. + */ + Namespace (char const* name, Namespace& parent) + : Registrar (parent) + { + assert (lua_istable (L, -1)); // Stack: parent namespace (pns) + + rawgetfield (L, -1, name); // Stack: pns, namespace (ns) | nil + + if (lua_isnil (L, -1)) // Stack: pns, nil + { + lua_pop (L, 1); // Stack: pns + + lua_newtable (L); // Stack: pns, ns + lua_pushvalue (L, -1); // Stack: pns, ns, ns + + // na.__metatable = ns + lua_setmetatable (L, -2); // Stack: pns, ns + + // ns.__index = indexMetaMethod + lua_pushcfunction (L, &CFunc::indexMetaMethod); + rawsetfield (L, -2, "__index"); // Stack: pns, ns + + // ns.__newindex = newindexMetaMethod + lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod); + rawsetfield (L, -2, "__newindex"); // Stack: pns, ns + + lua_newtable (L); // Stack: pns, ns, propget table (pg) + lua_rawsetp (L, -2, detail::getPropgetKey ()); // ns [propgetKey] = pg. Stack: pns, ns + + lua_newtable (L); // Stack: pns, ns, propset table (ps) + lua_rawsetp (L, -2, detail::getPropsetKey ()); // ns [propsetKey] = ps. Stack: pns, ns + + // pns [name] = ns + lua_pushvalue (L, -1); // Stack: pns, ns, ns + rawsetfield (L, -3, name); // Stack: pns, ns +#if 0 + lua_pushcfunction (L, &tostringMetaMethod); + rawsetfield (L, -2, "__tostring"); +#endif + } + + ++m_stackSize; + } + + //---------------------------------------------------------------------------- + /** + Close the class and continue the namespace registrations. + + @param child A child class registration object. + */ + explicit Namespace (ClassBase& child) + : Registrar (child) + { + } + + using Registrar::operator=; + +public: + //---------------------------------------------------------------------------- + /** + Retrieve the global namespace. + It is recommended to put your namespace inside the global namespace, and + then add your classes and functions to it, rather than adding many classes + and functions directly to the global namespace. + + @param L A Lua state. + @returns A namespace registration object. + */ + static Namespace getGlobalNamespace (lua_State* L) + { + enableExceptions (L); + return Namespace (L); + } + + //---------------------------------------------------------------------------- + /** + Open a new or existing namespace for registrations. + + @param name The namespace name. + @returns A namespace registration object. + */ + Namespace beginNamespace (char const* name) + { + assertIsActive (); + return Namespace (name, *this); + } + + //---------------------------------------------------------------------------- + /** + Continue namespace registration in the parent. + Do not use this on the global namespace. + + @returns A parent namespace registration object. + */ + Namespace endNamespace () + { + if (m_stackSize == 1) + { + throw std::logic_error ("endNamespace () called on global namespace"); + } + + assert (m_stackSize > 1); + --m_stackSize; + lua_pop (L, 1); + return Namespace (*this); + } + + //---------------------------------------------------------------------------- + /** + Add or replace a property. + + @param name The property name. + @param value A value pointer. + @param isWritable True for a read-write, false for read-only property. + @returns This namespace registration object. + */ + template + Namespace& addProperty (char const* name, T* value, bool isWritable = true) + { + return addVariable (name, value, isWritable); + } + + //---------------------------------------------------------------------------- + /** + Add or replace a property. + + @param name The property name. + @param value A value pointer. + @param isWritable True for a read-write, false for read-only property. + @returns This namespace registration object. + */ + template + Namespace& addVariable (char const* name, T* value, bool isWritable = true) + { + if (m_stackSize == 1) + { + throw std::logic_error ("addProperty () called on global namespace"); + } + + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + lua_pushlightuserdata (L, value); // Stack: ns, pointer + lua_pushcclosure (L, &CFunc::getVariable , 1); // Stack: ns, getter + CFunc::addGetter (L, name, -2); // Stack: ns + + if (isWritable) + { + lua_pushlightuserdata (L, value); // Stack: ns, pointer + lua_pushcclosure (L, &CFunc::setVariable , 1); // Stack: ns, setter + } + else + { + lua_pushstring (L, name); // Stack: ns, ps, name + lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: ns, error_fn + } + CFunc::addSetter (L, name, -2); // Stack: ns + + return *this; + } + + //---------------------------------------------------------------------------- + /** + Add or replace a property. + If the set function is omitted or null, the property is read-only. + + @param name The property name. + @param get A pointer to a property getter function. + @param set A pointer to a property setter function, optional. + @returns This namespace registration object. + */ + template + Namespace& addProperty (char const* name, TG (*get) (), void (*set) (TS) = 0) + { + if (m_stackSize == 1) + { + throw std::logic_error ("addProperty () called on global namespace"); + } + + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + lua_pushlightuserdata (L, reinterpret_cast (get)); // Stack: ns, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: ns, getter + CFunc::addGetter (L, name, -2); + + if (set != 0) + { + lua_pushlightuserdata(L, reinterpret_cast (set)); // Stack: ns, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); + } + else + { + lua_pushstring (L, name); + lua_pushcclosure (L, &CFunc::readOnlyError, 1); + } + CFunc::addSetter (L, name, -2); + + return *this; + } + + //---------------------------------------------------------------------------- + /** + Add or replace a property. + If the set function is omitted or null, the property is read-only. + + @param name The property name. + @param get A pointer to a property getter function. + @param set A pointer to a property setter function, optional. + @returns This namespace registration object. + */ + Namespace& addProperty (char const* name, int (*get) (lua_State*), int (*set) (lua_State*) = 0) + { + if (m_stackSize == 1) + { + throw std::logic_error ("addProperty () called on global namespace"); + } + + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + lua_pushcfunction (L, get); // Stack: ns, getter + CFunc::addGetter (L, name, -2); // Stack: ns + if (set != 0) + { + lua_pushcfunction(L, set); // Stack: ns, setter + CFunc::addSetter(L, name, -2); // Stack: ns + } + else + { + lua_pushstring(L, name); // Stack: ns, name + lua_pushcclosure(L, &CFunc::readOnlyError, 1); // Stack: ns, name, readOnlyError + CFunc::addSetter(L, name, -2); // Stack: ns + } + + return *this; + } + +#ifndef LUABRIDGE_CXX11 + + //---------------------------------------------------------------------------- + /** + Add or replace a function. + + @param name The function name. + @param fp A pointer to a function. + @returns This namespace registration object. + */ + template + Namespace& addFunction (char const* name, FP const fp) + { + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + lua_pushlightuserdata (L, reinterpret_cast (fp)); // Stack: ns, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: ns, function + rawsetfield (L, -2, name); // Stack: ns + + return *this; + } + +#else // ifndef LUABRIDGE_CXX11 + + //---------------------------------------------------------------------------- + /** + Add or replace a namespace function by std::function. + */ + template + Namespace& addFunction (char const* name, std::function function) + { + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + using FnType = decltype (function); + new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: ns, function userdata (ud) + lua_newtable (L); // Stack: ns, ud, ud metatable (mt) + lua_pushcfunction (L, &CFunc::gcMetaMethodAny ); // Stack: ns, ud, mt, gc function + rawsetfield (L, -2, "__gc"); // Stack: ns, ud, mt + lua_setmetatable (L, -2); // Stack: ns, ud + lua_pushcclosure (L, &CFunc::CallProxyFunctor ::f, 1); // Stack: ns, function + rawsetfield (L, -2, name); // Stack: ns + + return *this; + } + + //---------------------------------------------------------------------------- + /** + Add or replace a free function. + */ + template + Namespace& addFunction (char const* name, ReturnType (*fp) (Params...)) + { + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + using FnType = decltype (fp); + lua_pushlightuserdata (L, reinterpret_cast (fp)); // Stack: ns, function ptr + lua_pushcclosure (L, &CFunc::Call ::f, 1); // Stack: ns, function + rawsetfield (L, -2, name); // Stack: ns + + return *this; + } + +#endif // ifndef LUABRIDGE_CXX11 + + //---------------------------------------------------------------------------- + /** + Add or replace a lua_CFunction. + + @param name The function name. + @param fp A C-function pointer. + @returns This namespace registration object. + */ + Namespace& addFunction (char const* name, int (*const fp) (lua_State*)) + { + return addCFunction (name, fp); + } + + //---------------------------------------------------------------------------- + /** + Add or replace a lua_CFunction. + + @param name The function name. + @param fp A C-function pointer. + @returns This namespace registration object. + */ + Namespace& addCFunction (char const* name, int (*const fp) (lua_State*)) + { + assert (lua_istable (L, -1)); // Stack: namespace table (ns) + + lua_pushcfunction (L, fp); // Stack: ns, function + rawsetfield (L, -2, name); // Stack: ns + + return *this; + } + + //---------------------------------------------------------------------------- + /** + Open a new or existing class for registrations. + + @param name The class name. + @returns A class registration object. + */ + template + Class beginClass (char const* name) + { + assertIsActive (); + return Class (name, *this); + } + + //---------------------------------------------------------------------------- + /** + Derive a new class for registrations. + Call deriveClass() only once. + To continue registrations for the class later, use beginClass(). + + @param name The class name. + @returns A class registration object. + */ + template + Class deriveClass (char const* name) + { + assertIsActive (); + return Class (name, *this, detail::getStaticRegistryKey ()); + } +}; + +//------------------------------------------------------------------------------ +/** + Retrieve the global namespace. + It is recommended to put your namespace inside the global namespace, and + then add your classes and functions to it, rather than adding many classes + and functions directly to the global namespace. + + @param L A Lua state. + @returns A namespace registration object. +*/ +inline Namespace getGlobalNamespace (lua_State* L) +{ + return Namespace::getGlobalNamespace (L); +} + +} // namespace luabridge diff --git a/src/LuaBridge/detail/Security.h b/src/LuaBridge/detail/Security.h new file mode 100644 index 000000000..517254567 --- /dev/null +++ b/src/LuaBridge/detail/Security.h @@ -0,0 +1,62 @@ +#pragma once + +namespace luabridge { + +//------------------------------------------------------------------------------ +/** +security options. +*/ +class Security +{ +public: + static bool hideMetatables() + { + return getSettings().hideMetatables; + } + + static void setHideMetatables(bool shouldHide) + { + getSettings().hideMetatables = shouldHide; + } + +private: + struct Settings + { + Settings() : hideMetatables(true) + { + } + + bool hideMetatables; + }; + + static Settings& getSettings() + { + static Settings settings; + return settings; + } +}; + +//------------------------------------------------------------------------------ +/** +Set a global value in the lua_State. + +@note This works on any type specialized by `Stack`, including `LuaRef` and +its table proxies. +*/ +template +inline void setGlobal(lua_State* L, T t, char const* name) +{ + push(L, t); + lua_setglobal(L, name); +} + +//------------------------------------------------------------------------------ +/** +Change whether or not metatables are hidden (on by default). +*/ +inline void setHideMetatables(bool shouldHide) +{ + Security::setHideMetatables(shouldHide); +} + +} // namespace luabridge diff --git a/src/LuaBridge/detail/Stack.h b/src/LuaBridge/detail/Stack.h new file mode 100644 index 000000000..c3e2acaeb --- /dev/null +++ b/src/LuaBridge/detail/Stack.h @@ -0,0 +1,628 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { + +/// Lua stack traits for C++ types. +/// +/// @tparam T A C++ type. +/// +template +struct Stack; + +template <> +struct Stack +{ + static void push (lua_State* L) + { + } +}; + +//------------------------------------------------------------------------------ +/** + Receive the lua_State* as an argument. +*/ +template <> +struct Stack +{ + static lua_State* get (lua_State* L, int) + { + return L; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for a lua_CFunction. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, lua_CFunction f) + { + lua_pushcfunction (L, f); + } + + static lua_CFunction get (lua_State* L, int index) + { + return lua_tocfunction (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_iscfunction (L, index); + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `int`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, int value) + { + lua_pushinteger (L, static_cast (value)); + } + + static int get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `unsigned int`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, unsigned int value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned int get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `unsigned char`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, unsigned char value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned char get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `short`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, short value) + { + lua_pushinteger (L, static_cast (value)); + } + + static short get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `unsigned short`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, unsigned short value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned short get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `long`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, long value) + { + lua_pushinteger (L, static_cast (value)); + } + + static long get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `unsigned long`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, unsigned long value) + { + lua_pushinteger (L, static_cast (value)); + } + + static unsigned long get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + * Stack specialization for `long long`. + */ +template <> +struct Stack +{ + static void push (lua_State* L, long long value) + { + lua_pushinteger (L, static_cast (value)); + } + + static long long get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + * Stack specialization for `unsigned long long`. + */ +template <> +struct Stack +{ + static void push (lua_State* L, unsigned long long value) + { + lua_pushinteger (L, static_cast (value)); + } + static unsigned long long get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `float`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, float value) + { + lua_pushnumber (L, static_cast (value)); + } + + static float get (lua_State* L, int index) + { + return static_cast (luaL_checknumber (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `double`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, double value) + { + lua_pushnumber (L, static_cast (value)); + } + + static double get (lua_State* L, int index) + { + return static_cast (luaL_checknumber (L, index)); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TNUMBER; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `bool`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, bool value) + { + lua_pushboolean (L, value ? 1 : 0); + } + + static bool get (lua_State* L, int index) + { + return lua_toboolean (L, index) ? true : false; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_isboolean (L, index); + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `char`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, char value) + { + lua_pushlstring (L, &value, 1); + } + + static char get (lua_State* L, int index) + { + return luaL_checkstring (L, index) [0]; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TSTRING; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `const char*`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, char const* str) + { + if (str != 0) + lua_pushstring (L, str); + else + lua_pushnil (L); + } + + static char const* get (lua_State* L, int index) + { + return lua_isnil (L, index) ? 0 : luaL_checkstring (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return lua_isnil (L, index) || lua_type (L, index) == LUA_TSTRING; + } +}; + +//------------------------------------------------------------------------------ +/** + Stack specialization for `std::string`. +*/ +template <> +struct Stack +{ + static void push (lua_State* L, std::string const& str) + { + lua_pushlstring (L, str.data (), str.size ()); + } + + static std::string get (lua_State* L, int index) + { + size_t len; + if (lua_type (L, index) == LUA_TSTRING) + { + const char* str = lua_tolstring (L, index, &len); + return std::string (str, len); + } + + // Lua reference manual: + // If the value is a number, then lua_tolstring also changes the actual value in the stack to a string. + // (This change confuses lua_next when lua_tolstring is applied to keys during a table traversal.) + lua_pushvalue (L, index); + const char* str = lua_tolstring(L, -1, &len); + std::string string (str, len); + lua_pop (L, 1); // Pop the temporary string + return string; + } + + static bool isInstance (lua_State* L, int index) + { + return lua_type (L, index) == LUA_TSTRING; + } +}; + +namespace detail { + +template +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, T& value) + { + Stack ::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + +template +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, const T& value) + { + Stack ::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + +template +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, T* value) + { + Stack ::push (L, *value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + +template +struct StackOpSelector +{ + typedef T ReturnType; + + static void push (lua_State* L, const T* value) + { + Stack ::push (L, *value); + } + + static ReturnType get (lua_State* L, int index) + { + return Stack ::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Stack ::isInstance (L, index); + } +}; + +} // namespace detail + +template +struct Stack +{ + typedef detail::StackOpSelector ::value> Helper; + typedef typename Helper::ReturnType ReturnType; + + static void push (lua_State* L, T& value) + { + Helper::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Helper::get (L, index); + } +}; + +template +struct Stack +{ + typedef detail::StackOpSelector ::value> Helper; + typedef typename Helper::ReturnType ReturnType; + + static void push (lua_State* L, const T& value) + { + Helper::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Helper::get (L, index); + } +}; + +template +struct Stack +{ + typedef detail::StackOpSelector ::value> Helper; + typedef typename Helper::ReturnType ReturnType; + + static void push (lua_State* L, T* value) + { + Helper::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Helper::get (L, index); + } +}; + +template +struct Stack +{ + typedef detail::StackOpSelector ::value> Helper; + typedef typename Helper::ReturnType ReturnType; + + static void push (lua_State* L, const T* value) + { + Helper::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Helper::get (L, index); + } +}; + +//------------------------------------------------------------------------------ +/** + * Push an object onto the Lua stack. + */ +template +inline void push (lua_State* L, T t) +{ + Stack ::push (L, t); +} + +//------------------------------------------------------------------------------ +/** + * Check whether an object on the Lua stack is of type T. + */ +template +inline bool isInstance (lua_State* L, int index) +{ + return Stack ::isInstance (L, index); +} + +} // namespace luabridge diff --git a/src/LuaBridge/detail/TypeList.h b/src/LuaBridge/detail/TypeList.h new file mode 100644 index 000000000..83c018e9e --- /dev/null +++ b/src/LuaBridge/detail/TypeList.h @@ -0,0 +1,222 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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. + + This file incorporates work covered by the following copyright and + permission notice: + + The Loki Library + Copyright (c) 2001 by Andrei Alexandrescu + This code accompanies the book: + Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design + Patterns Applied". Copyright (c) 2001. Addison-Wesley. + Permission to use, copy, modify, distribute and sell this software for any + purpose is hereby granted without fee, provided that the above copyright + notice appear in all copies and that both that copyright notice and this + permission notice appear in supporting documentation. + The author or Addison-Welsey Longman make no representations about the + suitability of this software for any purpose. It is provided "as is" + without express or implied warranty. +*/ +//============================================================================== + +#pragma once + +#include +#include + +#include +#include + +namespace luabridge { + +namespace detail { + +/** + None type means void parameters or return value. +*/ +typedef void None; + +template +struct TypeList +{ + typedef Tail TailType; +}; + +template +struct TypeListSize +{ + static const size_t value = TypeListSize ::value + 1; +}; + +template <> +struct TypeListSize +{ + static const size_t value = 0; +}; + +#ifdef LUABRIDGE_CXX11 + +template +struct MakeTypeList; + +template +struct MakeTypeList +{ + using Result = TypeList ::Result>; +}; + +template <> +struct MakeTypeList <> +{ + using Result = None; +}; + +#endif + +/** + A TypeList with actual values. +*/ +template +struct TypeListValues +{ + static std::string const tostring (bool) + { + return ""; + } +}; + +/** + TypeListValues recursive template definition. +*/ +template +struct TypeListValues > +{ + Head hd; + TypeListValues tl; + + TypeListValues (Head hd_, TypeListValues const& tl_) + : hd (hd_), tl (tl_) + { + } + + static std::string tostring (bool comma = false) + { + std::string s; + + if (comma) + s = ", "; + + s = s + typeid (Head).name (); + + return s + TypeListValues ::tostring (true); + } +}; + +// Specializations of type/value list for head types that are references and +// const-references. We need to handle these specially since we can't count +// on the referenced object hanging around for the lifetime of the list. + +template +struct TypeListValues > +{ + Head hd; + TypeListValues tl; + + TypeListValues (Head& hd_, TypeListValues const& tl_) + : hd (hd_), tl (tl_) + { + } + + static std::string const tostring (bool comma = false) + { + std::string s; + + if (comma) + s = ", "; + + s = s + typeid (Head).name () + "&"; + + return s + TypeListValues ::tostring (true); + } +}; + +template +struct TypeListValues > +{ + Head hd; + TypeListValues tl; + + TypeListValues (Head const& hd_, const TypeListValues & tl_) + : hd (hd_), tl (tl_) + { + } + + static std::string const tostring (bool comma = false) + { + std::string s; + + if (comma) + s = ", "; + + s = s + typeid (Head).name () + " const&"; + + return s + TypeListValues ::tostring (true); + } +}; + +//============================================================================== +/** + Subclass of a TypeListValues constructable from the Lua stack. +*/ + +template +struct ArgList +{ +}; + +template +struct ArgList : public TypeListValues +{ + ArgList (lua_State*) + { + } +}; + +template +struct ArgList , Start> + : public TypeListValues > +{ + ArgList (lua_State* L) + : TypeListValues > (Stack ::get (L, Start), + ArgList (L)) + { + } +}; + +} // namespace detail + +} // namespace luabridge diff --git a/src/LuaBridge/detail/TypeTraits.h b/src/LuaBridge/detail/TypeTraits.h new file mode 100644 index 000000000..83a008f4a --- /dev/null +++ b/src/LuaBridge/detail/TypeTraits.h @@ -0,0 +1,136 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { + +//------------------------------------------------------------------------------ +/** + Container traits. + + Unspecialized ContainerTraits has the isNotContainer typedef for SFINAE. + All user defined containers must supply an appropriate specialization for + ContinerTraits (without the typedef isNotContainer). The containers that + come with LuaBridge also come with the appropriate ContainerTraits + specialization. See the corresponding declaration for details. + + A specialization of ContainerTraits for some generic type ContainerType + looks like this: + + template + struct ContainerTraits > + { + typedef typename T Type; + + static T* get (ContainerType const& c) + { + return c.get (); // Implementation-dependent on ContainerType + } + }; +*/ +template +struct ContainerTraits +{ + typedef bool isNotContainer; + typedef T Type; +}; + +namespace detail { + +//------------------------------------------------------------------------------ +/** + Type traits. + + Specializations return information about a type. +*/ +struct TypeTraits +{ + /** Determine if type T is a container. + + To be considered a container, there must be a specialization of + ContainerTraits with the required fields. + */ + template + class isContainer + { + private: + typedef char yes[1]; // sizeof (yes) == 1 + typedef char no [2]; // sizeof (no) == 2 + + template + static no& test (typename C::isNotContainer*); + + template + static yes& test (...); + + public: + static const bool value = sizeof (test >(0)) == sizeof (yes); + }; + + /** Determine if T is const qualified. + */ + /** @{ */ + template + struct isConst + { + static bool const value = false; + }; + + template + struct isConst + { + static bool const value = true; + }; + /** @} */ + + /** Remove the const qualifier from T. + */ + /** @{ */ + template + struct removeConst + { + typedef T Type; + }; + + template + struct removeConst + { + typedef T Type; + }; + /**@}*/ +}; + +} // namespace detail + +} // namespace luabridge diff --git a/src/LuaBridge/detail/Userdata.h b/src/LuaBridge/detail/Userdata.h new file mode 100644 index 000000000..97dee6918 --- /dev/null +++ b/src/LuaBridge/detail/Userdata.h @@ -0,0 +1,867 @@ +//------------------------------------------------------------------------------ +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 + +namespace luabridge { + +namespace detail { + +//============================================================================== +/** + Return the identity pointer for our lightuserdata tokens. + + Because of Lua's dynamic typing and our improvised system of imposing C++ + class structure, there is the possibility that executing scripts may + knowingly or unknowingly cause invalid data to get passed to the C functions + created by LuaBridge. In particular, our security model addresses the + following: + 1. Scripts cannot create a userdata (ignoring the debug lib). + 2. Scripts cannot create a lightuserdata (ignoring the debug lib). + 3. Scripts cannot set the metatable on a userdata. +*/ + +/** + Interface to a class pointer retrievable from a userdata. +*/ +class Userdata +{ +protected: + void* m_p; // subclasses must set this + + Userdata() : m_p (0) + { + } + + //-------------------------------------------------------------------------- + /** + Get an untyped pointer to the contained class. + */ + void* getPointer () + { + return m_p; + } + +private: + //-------------------------------------------------------------------------- + /** + Validate and retrieve a Userdata on the stack. + + The Userdata must exactly match the corresponding class table or + const table, or else a Lua error is raised. This is used for the + __gc metamethod. + */ + static Userdata* getExactClass (lua_State* L, int index, void const* /*classKey*/) + { + return static_cast (lua_touserdata (L, lua_absindex (L, index))); + } + + //-------------------------------------------------------------------------- + /** + Validate and retrieve a Userdata on the stack. + + The Userdata must be derived from or the same as the given base class, + identified by the key. If canBeConst is false, generates an error if + the resulting Userdata represents to a const object. We do the type check + first so that the error message is informative. + */ + static Userdata* getClass (lua_State* L, + int index, + void const* registryConstKey, + void const* registryClassKey, + bool canBeConst) + { + index = lua_absindex (L, index); + + lua_getmetatable (L, index); // Stack: object metatable (ot) | nil + if (!lua_istable (L, -1)) + { + lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: registry metatable (rt) | nil + return throwBadArg (L, index); + } + + lua_rawgetp (L, -1, getConstKey ()); // Stack: ot | nil, const table (co) | nil + assert (lua_istable (L, -1) || lua_isnil (L, -1)); + + // If const table is NOT present, object is const. Use non-const registry table + // if object cannot be const, so constness validation is done automatically. + // E.g. nonConstFn (constObj) + // -> canBeConst = false, isConst = true + // -> 'Class' registry table, 'const Class' object table + // -> 'expected Class, got const Class' + bool isConst = lua_isnil (L, -1); // Stack: ot | nil, nil, rt + if (isConst && canBeConst) + { + lua_rawgetp (L, LUA_REGISTRYINDEX, registryConstKey); // Stack: ot, nil, rt + } + else + { + lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: ot, co, rt + } + + lua_insert (L, -3); // Stack: rt, ot, co | nil + lua_pop (L, 1); // Stack: rt, ot + + for (;;) + { + if (lua_rawequal (L, -1, -2)) // Stack: rt, ot + { + lua_pop (L, 2); // Stack: - + return static_cast (lua_touserdata (L, index)); + } + + // Replace current metatable with it's base class. + lua_rawgetp (L, -1, getParentKey ()); // Stack: rt, ot, parent ot (pot) | nil + + if (lua_isnil (L, -1)) // Stack: rt, ot, nil + { + // Drop the object metatable because it may be some parent metatable + lua_pop (L, 2); // Stack: rt + return throwBadArg (L, index); + } + + lua_remove (L, -2); // Stack: rt, pot + } + + // no return + } + + static bool isInstance (lua_State* L, int index, void const* registryClassKey) + { + index = lua_absindex (L, index); + + int result = lua_getmetatable (L, index); // Stack: object metatable (ot) | nothing + if (result == 0) + { + return false; // Nothing was pushed on the stack + } + if (!lua_istable (L, -1)) + { + lua_pop (L, 1); // Stack: - + return false; + } + + lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: ot, rt + lua_insert (L, -2); // Stack: rt, ot + + for (;;) + { + if (lua_rawequal (L, -1, -2)) // Stack: rt, ot + { + lua_pop (L, 2); // Stack: - + return true; + } + + // Replace current metatable with it's base class. + lua_rawgetp (L, -1, getParentKey ()); // Stack: rt, ot, parent ot (pot) | nil + + if (lua_isnil (L, -1)) // Stack: rt, ot, nil + { + lua_pop (L, 3); // Stack: - + return false; + } + + lua_remove (L, -2); // Stack: rt, pot + } + } + + static Userdata* throwBadArg (lua_State* L, int index) + { + assert (lua_istable (L, -1) || lua_isnil (L, -1)); // Stack: rt | nil + + const char* expected = 0; + if (lua_isnil (L, -1)) // Stack: nil + { + expected = "unregistered class"; + } + else + { + lua_rawgetp (L, -1, getTypeKey ()); // Stack: rt, registry type + expected = lua_tostring (L, -1); + } + + const char* got = 0; + if (lua_isuserdata (L, index)) + { + lua_getmetatable (L, index); // Stack: ..., ot | nil + if (lua_istable (L, -1)) // Stack: ..., ot + { + lua_rawgetp (L, -1, getTypeKey ()); // Stack: ..., ot, object type | nil + if (lua_isstring (L, -1)) + { + got = lua_tostring (L, -1); + } + } + } + if (!got) + { + got = lua_typename (L, lua_type (L, index)); + } + + luaL_argerror (L, index, lua_pushfstring (L, "%s expected, got %s", expected, got)); + return 0; + } + +public: + virtual ~Userdata () { } + + //-------------------------------------------------------------------------- + /** + Returns the Userdata* if the class on the Lua stack matches. + If the class does not match, a Lua error is raised. + + @tparam T A registered user class. + @param L A Lua state. + @param index The index of an item on the Lua stack. + @returns A userdata pointer if the class matches. + */ + template + static Userdata* getExact (lua_State* L, int index) + { + return getExactClass (L, index, detail::getClassRegistryKey ()); + } + + //-------------------------------------------------------------------------- + /** + Get a pointer to the class from the Lua stack. + If the object is not the class or a subclass, or it violates the + const-ness, a Lua error is raised. + + @tparam T A registered user class. + @param L A Lua state. + @param index The index of an item on the Lua stack. + @param canBeConst TBD + @returns A pointer if the class and constness match. + */ + template + static T* get (lua_State* L, int index, bool canBeConst) + { + if (lua_isnil (L, index)) + return 0; + + return static_cast (getClass ( + L, index, detail::getConstRegistryKey (), + detail::getClassRegistryKey (), + canBeConst)->getPointer ()); + } + + template + static bool isInstance (lua_State* L, int index) + { + return isInstance (L, index, detail::getClassRegistryKey ()); + } +}; + +//---------------------------------------------------------------------------- +/** + Wraps a class object stored in a Lua userdata. + + The lifetime of the object is managed by Lua. The object is constructed + inside the userdata using placement new. +*/ +template +class UserdataValue : public Userdata +{ +private: + UserdataValue (UserdataValue const&); + UserdataValue operator= (UserdataValue const&); + + char m_storage [sizeof (T)]; + +private: + /** + Used for placement construction. + */ + UserdataValue () + { + m_p = 0; + } + + ~UserdataValue () + { + if (getPointer () != 0) + { + getObject ()->~T (); + } + } + +public: + /** + Push a T via placement new. + + The caller is responsible for calling placement new using the + returned uninitialized storage. + + @param L A Lua state. + @returns An object referring to the newly created userdata value. + */ + static UserdataValue * place (lua_State* const L) + { + UserdataValue * const ud = new ( + lua_newuserdata (L, sizeof (UserdataValue ))) UserdataValue (); + lua_rawgetp (L, LUA_REGISTRYINDEX, detail::getClassRegistryKey ()); + if (!lua_istable (L, -1)) + { + throw std::logic_error ("The class is not registered in LuaBridge"); + } + lua_setmetatable (L, -2); + return ud; + } + + /** + Push T via copy construction from U. + + @tparam U A container type. + @param L A Lua state. + @param u A container object reference. + */ + template + static inline void push (lua_State* const L, U const& u) + { + UserdataValue * ud = place (L); + new (ud->getObject ()) U (u); + ud->commit (); + } + + /** + Confirm object construction. + */ + void commit () + { + m_p = getObject (); + } + + T* getObject () + { + // If this fails to compile it means you forgot to provide + // a Container specialization for your container! + // + return reinterpret_cast (&m_storage [0]); + } +}; + +//---------------------------------------------------------------------------- +/** + Wraps a pointer to a class object inside a Lua userdata. + + The lifetime of the object is managed by C++. +*/ +class UserdataPtr : public Userdata +{ +private: + UserdataPtr (UserdataPtr const&); + UserdataPtr operator= (UserdataPtr const&); + +private: + /** Push a pointer to object using metatable key. + */ + static void push (lua_State* L, const void* p, void const* const key) + { + new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (const_cast (p)); + lua_rawgetp (L, LUA_REGISTRYINDEX, key); + if (!lua_istable (L, -1)) + { + lua_pop (L, 1); // possibly: a nil + throw std::logic_error ("The class is not registered in LuaBridge"); + } + lua_setmetatable (L, -2); + } + + explicit UserdataPtr (void* const p) + { + m_p = p; + + // Can't construct with a null pointer! + // + assert (m_p != 0); + } + +public: + /** Push non-const pointer to object. + + @tparam T A user registered class. + @param L A Lua state. + @param p A pointer to the user class instance. + */ + template + static void push (lua_State* const L, T* const p) + { + if (p) + push (L, p, getClassRegistryKey ()); + else + lua_pushnil (L); + } + + /** Push const pointer to object. + + @tparam T A user registered class. + @param L A Lua state. + @param p A pointer to the user class instance. + */ + template + static void push (lua_State* const L, T const* const p) + { + if (p) + push (L, p, getConstRegistryKey ()); + else + lua_pushnil (L); + } +}; + +//============================================================================ +/** + Wraps a container that references a class object. + + The template argument C is the container type, ContainerTraits must be + specialized on C or else a compile error will result. +*/ +template +class UserdataShared : public Userdata +{ +private: + UserdataShared (UserdataShared const&); + UserdataShared & operator= (UserdataShared const&); + + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + C m_c; + +private: + ~UserdataShared () + { + } + +public: + /** + Construct from a container to the class or a derived class. + + @tparam U A container type. + @param u A container object reference. + */ + template + explicit UserdataShared (U const& u) : m_c (u) + { + m_p = const_cast (reinterpret_cast ( + (ContainerTraits ::get (m_c)))); + } + + /** + Construct from a pointer to the class or a derived class. + + @tparam U A container type. + @param u A container object pointer. + */ + template + explicit UserdataShared (U* u) : m_c (u) + { + m_p = const_cast (reinterpret_cast ( + (ContainerTraits ::get (m_c)))); + } +}; + +//---------------------------------------------------------------------------- +// +// SFINAE helpers. +// + +// non-const objects +template +struct UserdataSharedHelper +{ + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static void push (lua_State* L, C const& c) + { + if (ContainerTraits ::get (c) != 0) + { + new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (c); + lua_rawgetp (L, LUA_REGISTRYINDEX, getClassRegistryKey ()); + // If this goes off it means the class T is unregistered! + assert (lua_istable (L, -1)); + lua_setmetatable (L, -2); + } + else + { + lua_pushnil (L); + } + } + + static void push (lua_State* L, T* const t) + { + if (t) + { + new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (t); + lua_rawgetp (L, LUA_REGISTRYINDEX, getClassRegistryKey ()); + // If this goes off it means the class T is unregistered! + assert (lua_istable (L, -1)); + lua_setmetatable (L, -2); + } + else + { + lua_pushnil (L); + } + } +}; + +// const objects +template +struct UserdataSharedHelper +{ + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static void push (lua_State* L, C const& c) + { + if (ContainerTraits ::get (c) != 0) + { + new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (c); + lua_rawgetp (L, LUA_REGISTRYINDEX, getConstRegistryKey ()); + // If this goes off it means the class T is unregistered! + assert (lua_istable (L, -1)); + lua_setmetatable (L, -2); + } + else + { + lua_pushnil (L); + } + } + + static void push (lua_State* L, T* const t) + { + if (t) + { + new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (t); + lua_rawgetp (L, LUA_REGISTRYINDEX, getConstRegistryKey ()); + // If this goes off it means the class T is unregistered! + assert (lua_istable (L, -1)); + lua_setmetatable (L, -2); + } + else + { + lua_pushnil (L); + } + } +}; + +/** + Pass by container. + + The container controls the object lifetime. Typically this will be a + lifetime shared by C++ and Lua using a reference count. Because of type + erasure, containers like std::shared_ptr will not work. Containers must + either be of the intrusive variety, or in the style of the RefCountedPtr + type provided by LuaBridge (that uses a global hash table). +*/ +template +struct StackHelper +{ + static void push (lua_State* L, C const& c) + { + UserdataSharedHelper ::Type>::value>::push (L, c); + } + + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static C get (lua_State* L, int index) + { + return Userdata::get (L, index, true); + } +}; + +/** + Pass by value. + + Lifetime is managed by Lua. A C++ function which accesses a pointer or + reference to an object outside the activation record in which it was + retrieved may result in undefined behavior if Lua garbage collected it. +*/ +template +struct StackHelper +{ + static inline void push (lua_State* L, T const& t) + { + UserdataValue ::push (L, t); + } + + static inline T const& get (lua_State* L, int index) + { + return *Userdata::get (L, index, true); + } +}; + + +//------------------------------------------------------------------------------ +/** + Lua stack conversions for pointers and references to class objects. + + Lifetime is managed by C++. Lua code which remembers a reference to the + value may result in undefined behavior if C++ destroys the object. The + handling of the const and volatile qualifiers happens in UserdataPtr. +*/ + +template +struct RefStackHelper +{ + typedef C return_type; + + static inline void push (lua_State* L, C const& t) + { + UserdataSharedHelper ::Type>::value>::push (L, t); + } + + typedef typename TypeTraits::removeConst < + typename ContainerTraits ::Type>::Type T; + + static return_type get (lua_State* L, int index) + { + return Userdata::get (L, index, true); + } +}; + +template +struct RefStackHelper +{ + typedef T& return_type; + + static void push (lua_State* L, T const& t) + { + UserdataPtr::push (L, &t); + } + + static return_type get (lua_State* L, int index) + { + T* t = Userdata::get (L, index, true); + + if (!t) + luaL_error (L, "nil passed to reference"); + return *t; + } +}; + + +/** + * Voider class template. Used to force a comiler to instantiate + * an otherwise probably unused template parameter type T. + * See the C++20 std::void_t <> for details. + */ +template +struct Void +{ + typedef void Type; +}; + + +/** + * Trait class that selects whether to return a user registered + * class object by value or by reference. + */ + +template +struct UserdataGetter +{ + typedef T* ReturnType; + + static ReturnType get (lua_State* L, int index) + { + return Userdata::get (L, index, false); + } +}; + +template +struct UserdataGetter ::Type> +{ + typedef T ReturnType; + + static ReturnType get (lua_State* L, int index) + { + return StackHelper ::value>::get (L, index); + } +}; + +} // namespace detail + +//============================================================================== + +/** + Lua stack conversions for class objects passed by value. +*/ +template +struct Stack +{ + typedef void IsUserdata; + + typedef detail::UserdataGetter Getter; + typedef typename Getter::ReturnType ReturnType; + + static void push (lua_State* L, T const& value) + { + using namespace detail; + StackHelper ::value>::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Getter::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return detail::Userdata::isInstance (L, index); + } +}; + +namespace detail { + +/** + * Trait class indicating whether the parameter type must be + * a user registered class. The trait checks the existence of + * member type Stack::IsUserdata specialization for detection. + */ +template +struct IsUserdata +{ + static const bool value = false; +}; + +template +struct IsUserdata ::IsUserdata>::Type> +{ + static const bool value = true; +}; + + +/** + * Trait class that selects a specific push/get implemenation. + */ +template +struct StackOpSelector; + +// pointer +template +struct StackOpSelector +{ + typedef T* ReturnType; + + static void push (lua_State* L, T* value) + { + UserdataPtr::push (L, value); + } + + static T* get (lua_State* L, int index) + { + return Userdata::get (L, index, false); + } + + static bool isInstance (lua_State* L, int index) + { + return Userdata::isInstance (L, index); + } +}; + +// pointer to const +template +struct StackOpSelector +{ + typedef const T* ReturnType; + + static void push (lua_State* L, const T* value) + { + UserdataPtr::push (L, value); + } + + static const T* get (lua_State* L, int index) + { + return Userdata::get (L, index, true); + } + + static bool isInstance (lua_State* L, int index) + { + return Userdata::isInstance (L, index); + } +}; + +// reference +template +struct StackOpSelector +{ + typedef RefStackHelper ::value> Helper; + typedef typename Helper::return_type ReturnType; + + static void push (lua_State* L, T& value) + { + UserdataPtr::push (L, &value); + } + + static ReturnType get (lua_State* L, int index) + { + return Helper::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Userdata::isInstance (L, index); + } +}; + +// reference to const +template +struct StackOpSelector +{ + typedef RefStackHelper ::value> Helper; + typedef typename Helper::return_type ReturnType; + + static void push (lua_State* L, const T& value) + { + Helper::push (L, value); + } + + static ReturnType get (lua_State* L, int index) + { + return Helper::get (L, index); + } + + static bool isInstance (lua_State* L, int index) + { + return Userdata::isInstance (L, index); + } +}; + +} // namespace detail + +} // namespace luabridge diff --git a/src/LuaBridge/detail/dump.h b/src/LuaBridge/detail/dump.h new file mode 100644 index 000000000..7e23f9f5c --- /dev/null +++ b/src/LuaBridge/detail/dump.h @@ -0,0 +1,143 @@ +//============================================================================== +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2019, Dmitry Tarakanov + Copyright 2012, Vinnie Falco + Copyright 2007, Nathan Reed + + License: The MIT License (http://www.opensource.org/licenses/mit-license.php) + + 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 "LuaBridge/detail/ClassInfo.h" + +#include +#include + + +namespace luabridge { +namespace debug { + +inline void putIndent (std::ostream& stream, unsigned level) +{ + for (unsigned i = 0; i < level; ++i) + { + stream << " "; + } +} + +inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level); + +inline void dumpValue (lua_State* L, int index, std::ostream& stream, unsigned level = 0) +{ + const int type = lua_type (L, index); + switch (type) + { + case LUA_TNIL: + stream << "nil"; + break; + + case LUA_TBOOLEAN: + stream << (lua_toboolean (L, index) ? "true" : "false"); + break; + + case LUA_TNUMBER: + stream << lua_tonumber (L, index); + break; + + case LUA_TSTRING: + stream << '"' << lua_tostring (L, index) << '"'; + break; + + case LUA_TFUNCTION: + if (lua_iscfunction (L, index)) + { + stream << "cfunction@" << lua_topointer (L, index); + } + else + { + stream << "function@" << lua_topointer (L, index); + } + break; + + case LUA_TTHREAD: + stream << "thread@" << lua_tothread (L, index); + break; + + case LUA_TLIGHTUSERDATA: + stream << "lightuserdata@" << lua_touserdata (L, index); + break; + + case LUA_TTABLE: + dumpTable (L, index, stream, level); + break; + + case LUA_TUSERDATA: + stream << "userdata@" << lua_touserdata (L, index); + break; + + default: + stream << lua_typename (L, type);; + break; + } +} + +inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level) +{ + stream << "table@" << lua_topointer (L, index); + + if (level > 0) + { + return; + } + + index = lua_absindex (L, index); + stream << " {"; + lua_pushnil (L); // Initial key + while (lua_next (L, index)) + { + stream << "\n"; + putIndent (stream, level + 1); + dumpValue (L, -2, stream, level + 1); // Key + stream << ": "; + dumpValue (L, -1, stream, level + 1); // Value + lua_pop (L, 1); // Value + } + putIndent (stream, level); + stream << "\n}"; +} + +inline void dumpState (lua_State *L, std::ostream& stream = std::cerr) +{ + int top = lua_gettop (L); + for (int i = 1; i <= top; ++i) + { + stream << "stack #" << i << ": "; + dumpValue (L, i, stream, 0); + stream << "\n"; + } +} + +} // namespace debug +} // namespace luabridge diff --git a/src/NotepadNext.pro b/src/NotepadNext.pro new file mode 100644 index 000000000..72b031abe --- /dev/null +++ b/src/NotepadNext.pro @@ -0,0 +1,78 @@ +# This file is part of Notepad Next. +# Copyright 2019 Justin Dailey +# +# Notepad Next 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, either version 3 of the License, or +# (at your option) any later version. +# +# Notepad Next 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. +# +# You should have received a copy of the GNU General Public License +# along with Notepad Next. If not, see . + + +include(Version.pri) + +!versionAtLeast(QT_VERSION, 5.15):error("Qt v5.15 or greater is required") + +TEMPLATE = subdirs + +SUBDIRS = NotepadNext + + +# Extra Windows targets +win32 { + # Package up the EXE with all the other needed files + package.target = package + package.commands = \ + xcopy $$shell_path($${OUT_PWD}/NotepadNext/NotepadNext.exe) $$shell_path($${OUT_PWD}/package/) /Y && \ + xcopy $$shell_path($${OUT_PWD}/NotepadNext/*.dll) $$shell_path($${OUT_PWD}/package/) /Y && \ + xcopy $$shell_path($${OUT_PWD}/NotepadNext/LICENSE) $$shell_path($${OUT_PWD}/package/) /Y && + + equals(QT_MAJOR_VERSION, 6) { + package.commands += windeployqt --release --no-translations --no-system-d3d-compiler --no-compiler-runtime --no-opengl-sw $$shell_path($${OUT_PWD}/package/NotepadNext.exe) + } else { + package.commands += windeployqt --release --no-translations --no-system-d3d-compiler --no-compiler-runtime --no-angle --no-opengl-sw $$quote($$shell_path($${OUT_PWD}/package/NotepadNext.exe)) && + package.commands += del $$quote($$shell_path($${OUT_PWD}/package/imageformats/qjpeg.dll)) $$quote($$shell_path($${OUT_PWD}/package/imageformats/qtiff.dll)) $$quote($$shell_path($${OUT_PWD}/package/imageformats/qwebp.dll)) + } + + # Zip it up + zip.target = zip + zip.depends = package + zip.commands = 7z a -tzip $$quote(NotepadNext-v$${APP_VERSION}.zip) $$shell_path(./package/*) -x!libssl-1_1-x64.dll -x!libcrypto-1_1-x64.dll + + # Build the Installer + installer.target = installer + installer.depends = package + installer.commands = makensis /V4 $$shell_path($${OUT_PWD}/../installer/installer.nsi) + + QMAKE_EXTRA_TARGETS += package zip installer +} + +macos { + dmg.target = dmg + dmg.commands = \ + cd NotepadNext && \ + macdeployqt "NotepadNext.app" -dmg && \ + mv NotepadNext.dmg NotepadNext-v$${APP_VERSION}.dmg + + QMAKE_EXTRA_TARGETS += dmg +} + +linux { + appimage.target = appimage + appimage.commands = \ + make install INSTALL_ROOT=AppDir && \ + cd NotepadNext && \ + wget --no-verbose "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" && \ + wget --no-verbose "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" && \ + chmod +x linuxdeploy*.AppImage && \ + export OUTPUT=NotepadNext-v$${APP_VERSION}-x86_64.AppImage && \ + ./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt --output appimage + + QMAKE_EXTRA_TARGETS += appimage +} diff --git a/src/NotepadNext/ApplicationSettings.cpp b/src/NotepadNext/ApplicationSettings.cpp new file mode 100644 index 000000000..059bedffd --- /dev/null +++ b/src/NotepadNext/ApplicationSettings.cpp @@ -0,0 +1,69 @@ +/* + * This file is part of Notepad Next. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "ApplicationSettings.h" + +#include +#include + +#define CREATE_SETTING(group, name, lname, type, default) \ +ApplicationSetting name{#group "/" #name, default};\ + type ApplicationSettings::lname() const\ +{\ + return get(name);\ +}\ + void ApplicationSettings::set##name(type lname)\ +{\ + set(name, lname);\ + emit lname##Changed(lname);\ +} + + + +ApplicationSettings::ApplicationSettings(QObject *parent) + : QSettings{parent} +{ +} + +CREATE_SETTING(Gui, ShowMenuBar, showMenuBar, bool, true) +CREATE_SETTING(Gui, ShowToolBar, showToolBar, bool, true) +CREATE_SETTING(Gui, ShowTabBar, showTabBar, bool, true) +CREATE_SETTING(Gui, ShowStatusBar, showStatusBar, bool, true) +CREATE_SETTING(Gui, CenterSearchDialog, centerSearchDialog, bool, true) + +CREATE_SETTING(Gui, TabsClosable, tabsClosable, bool, true) +CREATE_SETTING(Gui, ExitOnLastTabClosed, exitOnLastTabClosed, bool, false) + +CREATE_SETTING(Gui, CombineSearchResults, combineSearchResults, bool, false) + +CREATE_SETTING(Gui, DarkMode, darkMode, bool, true) + +CREATE_SETTING(App, RestorePreviousSession, restorePreviousSession, bool, false) +CREATE_SETTING(App, RestoreUnsavedFiles, restoreUnsavedFiles, bool, false) +CREATE_SETTING(App, RestoreTempFiles, restoreTempFiles, bool, false) + +CREATE_SETTING(App, Translation, translation, QString, QStringLiteral("")) + +CREATE_SETTING(Editor, ShowWhitespace, showWhitespace, bool, false); +CREATE_SETTING(Editor, ShowEndOfLine, showEndOfLine, bool, false); +CREATE_SETTING(Editor, ShowWrapSymbol, showWrapSymbol, bool, false); +CREATE_SETTING(Editor, ShowIndentGuide, showIndentGuide, bool, true); +CREATE_SETTING(Editor, WordWrap, wordWrap, bool, false) +CREATE_SETTING(Editor, FontName, fontName, QString, QStringLiteral("Courier New")) +CREATE_SETTING(Editor, FontSize, fontSize, int, []() { return qApp->font().pointSize() + 2; }) +CREATE_SETTING(Editor, AdditionalWordChars, additionalWordChars, QString, QStringLiteral("")); diff --git a/src/NotepadNext/ApplicationSettings.h b/src/NotepadNext/ApplicationSettings.h new file mode 100644 index 000000000..cfa0eceec --- /dev/null +++ b/src/NotepadNext/ApplicationSettings.h @@ -0,0 +1,112 @@ +/* + * This file is part of Notepad Next. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + +#include + +#include +#include +#include + + +template +class ApplicationSetting +{ +public: + ApplicationSetting(const char * const key, T defaultValue = T()) + : mKey(key) + , mDefault(defaultValue) + , mCallable(Q_NULLPTR) + {} + + ApplicationSetting(const char * const key, std::function callable) + : mKey(key) + , mDefault(T()) + , mCallable(callable) + {} + + inline T getDefault() const { return mCallable ? mCallable() : mDefault ; } + inline const char * const key() const { return mKey; } + +private: + const char * const mKey; + const T mDefault; + std::function mCallable; +}; + + +#define DEFINE_SETTING(name, lname, type)\ +public:\ + type lname() const;\ +public slots:\ + void set##name(type lname);\ +Q_SIGNAL\ + void lname##Changed(type lname);\ + + +class ApplicationSettings : public QSettings +{ + Q_OBJECT + +public: + explicit ApplicationSettings(QObject *parent = nullptr); + +public: + template + T get(const char *key, const T &defaultValue) const + { return value(QLatin1String(key), defaultValue).template value(); } + + template + T get(const ApplicationSetting &setting) const + { return get(setting.key(), setting.getDefault()); } + + template + void set(const ApplicationSetting &setting, const T &value) + { setValue(QLatin1String(setting.key()), value); } + +public: + DEFINE_SETTING(ShowMenuBar, showMenuBar, bool) + DEFINE_SETTING(ShowToolBar, showToolBar, bool) + DEFINE_SETTING(ShowTabBar, showTabBar, bool) + DEFINE_SETTING(ShowStatusBar, showStatusBar, bool) + DEFINE_SETTING(CenterSearchDialog, centerSearchDialog, bool) + + DEFINE_SETTING(TabsClosable, tabsClosable, bool) + DEFINE_SETTING(ExitOnLastTabClosed, exitOnLastTabClosed, bool) + + DEFINE_SETTING(CombineSearchResults, combineSearchResults, bool) + + DEFINE_SETTING(RestorePreviousSession, restorePreviousSession, bool) + DEFINE_SETTING(RestoreUnsavedFiles, restoreUnsavedFiles, bool) + DEFINE_SETTING(RestoreTempFiles, restoreTempFiles, bool) + + DEFINE_SETTING(Translation, translation, QString) + + DEFINE_SETTING(ShowWhitespace, showWhitespace, bool); + DEFINE_SETTING(ShowEndOfLine, showEndOfLine, bool); + DEFINE_SETTING(ShowWrapSymbol, showWrapSymbol, bool) + DEFINE_SETTING(ShowIndentGuide, showIndentGuide, bool) + DEFINE_SETTING(WordWrap, wordWrap, bool); + DEFINE_SETTING(FontName, fontName, QString); + DEFINE_SETTING(FontSize, fontSize, int); + DEFINE_SETTING(AdditionalWordChars, additionalWordChars, QString); + + DEFINE_SETTING(DarkMode, darkMode, bool) +}; diff --git a/src/NotepadNext/ColorPickerDelegate.cpp b/src/NotepadNext/ColorPickerDelegate.cpp new file mode 100644 index 000000000..6bb3ea0dd --- /dev/null +++ b/src/NotepadNext/ColorPickerDelegate.cpp @@ -0,0 +1,55 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "ColorPickerDelegate.h" + +#include + +ColorPickerDelegate::ColorPickerDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ +} + +QWidget *ColorPickerDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option) + Q_UNUSED(index) + + QColorDialog* colorDialog = new QColorDialog(parent); + colorDialog->setModal(true); + + return colorDialog; +} + +void ColorPickerDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + QColorDialog *colorDialog = static_cast(editor); + const QColor color = index.model()->data(index, Qt::DecorationRole).value(); + + colorDialog->setCurrentColor(color); +} + +void ColorPickerDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + QColorDialog *colorDialog = static_cast(editor); + QColor color = colorDialog->selectedColor(); + + if (color.isValid()) { + model->setData(index, color, Qt::EditRole); + } +} diff --git a/src/NotepadNext/ColorPickerDelegate.h b/src/NotepadNext/ColorPickerDelegate.h new file mode 100644 index 000000000..312624ad8 --- /dev/null +++ b/src/NotepadNext/ColorPickerDelegate.h @@ -0,0 +1,37 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef COLORPICKERDELEGATE_H +#define COLORPICKERDELEGATE_H + +#include + +class ColorPickerDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + ColorPickerDelegate(QObject *parent = nullptr); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; +}; + +#endif // COLORPICKERDELEGATE_H diff --git a/src/NotepadNext/ComboBoxDelegate.cpp b/src/NotepadNext/ComboBoxDelegate.cpp new file mode 100644 index 000000000..42065ed38 --- /dev/null +++ b/src/NotepadNext/ComboBoxDelegate.cpp @@ -0,0 +1,87 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "ComboBoxDelegate.h" + +#include +#include + + +ComboBoxDelegate::ComboBoxDelegate(const QList &items, QObject *parent) + : QStyledItemDelegate(parent), comboBoxItems(items) +{ +} + +QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option) + Q_UNUSED(index) + + QComboBox *comboBox = new QComboBox(parent); + + for(const ComboBoxItem &item : comboBoxItems) { + comboBox->addItem(item.first, item.second); + } + + return comboBox; +} + +void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + QVariant value = index.model()->data(index, Qt::EditRole); + QComboBox *comboBox = static_cast(editor); + + comboBox->setCurrentIndex(comboBox->findData(value)); +} + +void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + QComboBox *comboBox = static_cast(editor); + QVariant value = comboBox->currentData(); + + model->setData(index, value, Qt::EditRole); +} + +void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(index) + + editor->setGeometry(option.rect); +} + + +QSize ComboBoxDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option) + Q_UNUSED(index) + + QFontMetrics fm = qApp->fontMetrics(); + QSize maxStringSize(0, 0); + int &width = maxStringSize.rwidth(); + int &height = maxStringSize.rheight(); + + for(const ComboBoxItem &item : comboBoxItems) { + QRect rect = fm.boundingRect(item.first); + + height = rect.height(); // Heights *should* all be the same + width = qMax(rect.width(), width); + } + + QStyleOptionComboBox comobBoxStyleOptions; + return qApp->style()->sizeFromContents(QStyle::CT_ComboBox, &comobBoxStyleOptions, maxStringSize, nullptr); +} diff --git a/src/NotepadNext/ComboBoxDelegate.h b/src/NotepadNext/ComboBoxDelegate.h new file mode 100644 index 000000000..b86a46a7c --- /dev/null +++ b/src/NotepadNext/ComboBoxDelegate.h @@ -0,0 +1,45 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef COMBOBOXDELEGATE_H +#define COMBOBOXDELEGATE_H + +#include + +using ComboBoxItem = QPair; + +class ComboBoxDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + ComboBoxDelegate(const QList &items, QObject *parent = nullptr); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; + + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +private: + QList comboBoxItems; +}; + +#endif // COMBOBOXDELEGATE_H diff --git a/src/NotepadNext/Converter.cpp b/src/NotepadNext/Converter.cpp new file mode 100644 index 000000000..ae1016f02 --- /dev/null +++ b/src/NotepadNext/Converter.cpp @@ -0,0 +1,36 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "Converter.h" + +Converter::Converter(ScintillaNext *editor) : + editor(editor) +{ +} + +void Converter::convert(QTextStream &stream) +{ + convertRange(stream, 0, editor->length()); +} + +void Converter::ensureDocumentStyled(int start, int end) +{ + // If idle styling is used, then the document may not have styling information yet + editor->colourise(start, end); +} diff --git a/src/NotepadNext/Converter.h b/src/NotepadNext/Converter.h new file mode 100644 index 000000000..3324a3024 --- /dev/null +++ b/src/NotepadNext/Converter.h @@ -0,0 +1,39 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + +#include + +#include "ScintillaNext.h" + +class Converter +{ +public: + Converter(ScintillaNext *editor); + + void convert(QTextStream &stream); + virtual void convertRange(QTextStream &stream, int start, int end) = 0; + +protected: + void ensureDocumentStyled(int start, int end); + + ScintillaNext *editor; +}; + diff --git a/src/NotepadNext/DebugManager.cpp b/src/NotepadNext/DebugManager.cpp new file mode 100644 index 000000000..8ab467eb1 --- /dev/null +++ b/src/NotepadNext/DebugManager.cpp @@ -0,0 +1,85 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "DebugManager.h" + +#include + + +Q_GLOBAL_STATIC(QList, handlers); +Q_GLOBAL_STATIC(QStringList, buffered_debug_output); +QtMessageHandler original = Q_NULLPTR; + +static void buffer_debug_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + buffered_debug_output->append(qFormatLogMessage(type, context, msg)); + + original(type, context, msg); +} + +static void debug_manager_handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + const QString log_message = qFormatLogMessage(type, context, msg); + for (DebugOutputHandler handler : *handlers) { + handler(log_message); + } + + original(type, context, msg); +} + + +void DebugManager::manageDebugOutput() +{ + // Just to be safe, restore the original message handler + qInstallMessageHandler(0); + + // Clear the list if it was ever used previously + handlers->clear(); + + // Install our own custom handler + original = qInstallMessageHandler(debug_manager_handler); +} + +void DebugManager::pauseDebugOutput() +{ + // Just to be safe, restore the original message handler + qInstallMessageHandler(0); + + buffered_debug_output->clear(); + + original = qInstallMessageHandler(buffer_debug_output); +} + +void DebugManager::resumeDebugOutput() +{ + for (DebugOutputHandler handler : *handlers) { + for (const QString &msg : *buffered_debug_output) { + handler(msg); + } + } + + buffered_debug_output->clear(); + + qInstallMessageHandler(debug_manager_handler); +} + +void DebugManager::addMessageHandler(DebugOutputHandler handler) +{ + handlers->append(handler); +} diff --git a/src/NotepadNext/DebugManager.h b/src/NotepadNext/DebugManager.h new file mode 100644 index 000000000..cfb3c893f --- /dev/null +++ b/src/NotepadNext/DebugManager.h @@ -0,0 +1,34 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef DEBUGMANAGER_H +#define DEBUGMANAGER_H + +#include + +typedef void (*DebugOutputHandler)(const QString &str); + +namespace DebugManager { + void manageDebugOutput(); + void pauseDebugOutput(); + void resumeDebugOutput(); + void addMessageHandler(DebugOutputHandler handler); +} + +#endif // DEBUGMANAGER_H diff --git a/src/NotepadNext/DockedEditor.cpp b/src/NotepadNext/DockedEditor.cpp new file mode 100644 index 000000000..9287b8182 --- /dev/null +++ b/src/NotepadNext/DockedEditor.cpp @@ -0,0 +1,236 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "DockedEditor.h" +#include "DockAreaTabBar.h" +#include "DockAreaWidget.h" +#include "DockWidgetTab.h" +#include "DockComponentsFactory.h" +#include "DockedEditorTitleBar.h" +#include "DockAreaTitleBar.h" + +#include "ScintillaNext.h" + +#include + + +class DockedEditorComponentsFactory : public ads::CDockComponentsFactory +{ +public: + ads::CDockAreaTitleBar* createDockAreaTitleBar(ads::CDockAreaWidget* DockArea) const { + DockedEditorTitleBar *titleBar = new DockedEditorTitleBar(DockArea); + + // Disable the built in context menu for the title bar since it has options we don't want + titleBar->setContextMenuPolicy(Qt::NoContextMenu); + + return titleBar; + } +}; + + +DockedEditor::DockedEditor(QWidget *parent) : QObject(parent) +{ + ads::CDockComponentsFactory::setFactory(new DockedEditorComponentsFactory()); + + ads::CDockManager::setConfigFlag(ads::CDockManager::AllTabsHaveCloseButton, true); + ads::CDockManager::setConfigFlag(ads::CDockManager::AlwaysShowTabs, true); + ads::CDockManager::setConfigFlag(ads::CDockManager::OpaqueSplitterResize, true); + ads::CDockManager::setConfigFlag(ads::CDockManager::DragPreviewIsDynamic, true); + ads::CDockManager::setConfigFlag(ads::CDockManager::DragPreviewShowsContentPixmap, true); + ads::CDockManager::setConfigFlag(ads::CDockManager::DockAreaHasCloseButton, false); + ads::CDockManager::setConfigFlag(ads::CDockManager::DockAreaHasUndockButton, false); + // When tabs title/text elide disabled and lots of tabs opened, tabs menu button will not show + // as it only shows when tab title elided. + // So disable dynamic tabs menu visibility. + ads::CDockManager::setConfigFlag(ads::CDockManager::DockAreaDynamicTabsMenuButtonVisibility, false); + ads::CDockManager::setConfigFlag(ads::CDockManager::FocusHighlighting, true); + ads::CDockManager::setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true); + ads::CDockManager::setConfigFlag(ads::CDockManager::MiddleMouseButtonClosesTab, true); + + dockManager = new ads::CDockManager(parent); + dockManager->setStyleSheet(""); + + connect(dockManager, &ads::CDockManager::focusedDockWidgetChanged, this, [=](ads::CDockWidget* old, ads::CDockWidget* now) { + Q_UNUSED(old) + + ScintillaNext *editor = qobject_cast(now->widget()); + + currentEditor = editor; + editor->grabFocus(); + emit editorActivated(editor); + }); + + connect(dockManager, &ads::CDockManager::dockAreaCreated, this, [=](ads::CDockAreaWidget* DockArea) { + DockedEditorTitleBar *titleBar = qobject_cast(DockArea->titleBar()); + connect(titleBar, &DockedEditorTitleBar::doubleClicked, this, &DockedEditor::titleBarDoubleClicked); + + connect(DockArea->titleBar()->tabBar(), &ads::CDockAreaTabBar::tabMoved, this, [=](int from, int to) { + Q_UNUSED(from); + Q_UNUSED(to); + + emit editorOrderChanged(); + }); + + // In theory the order changes when a new dock area is created (e.g. editor is dragged and dropped), + // but the dockAreaCreated() signal is triggered before it is actually added to the CDockManager, + // so interrogating the dock manager during the signal doesn't help. + //emit editorOrderChanged(); + }); +} + + +ScintillaNext *DockedEditor::getCurrentEditor() const +{ + return currentEditor; +} + +int DockedEditor::count() const +{ + int total = 0; + + for (int i = 0; i < dockManager->dockAreaCount(); ++i) + total += dockManager->dockArea(i)->dockWidgetsCount(); + + return total; +} + +QVector DockedEditor::editors() const +{ + QVector editors; + + // For each area, for each widget, append it to our list + for (const ads::CDockAreaWidget* areaWidget : dockManager->openedDockAreas()) { + for (const ads::CDockWidget* dockWidget : areaWidget->dockWidgets()) { + editors.append(qobject_cast(dockWidget->widget())); + } + } + + return editors; +} + +void DockedEditor::switchToEditor(const ScintillaNext *editor) +{ + ads::CDockWidget *dockWidget = qobject_cast(editor->parentWidget()); + + if (dockWidget == Q_NULLPTR) { + qWarning() << "Expected editor's parent to be CDockWidget"; + } + else { + dockWidget->raise(); + } +} + +void DockedEditor::dockWidgetCloseRequested() +{ + ads::CDockWidget *dockWidget = qobject_cast(sender()); + ScintillaNext *editor = qobject_cast(dockWidget->widget()); + + emit editorCloseRequested(editor); +} + +ads::CDockAreaWidget *DockedEditor::currentDockArea() const +{ + const ads::CDockWidget *dockWidget = dockManager->focusedDockWidget(); + + if (dockWidget) { + return dockWidget->dockAreaWidget(); + } + else { + return Q_NULLPTR; + } +} + +void DockedEditor::addEditor(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + Q_ASSERT(editor != Q_NULLPTR); + + if (currentEditor == Q_NULLPTR) { + currentEditor = editor; + } + + // Create the dock widget for the editor + ads::CDockWidget *dockWidget = new ads::CDockWidget(editor->getName()); + + // Disable elide, elided file names not readable when lots of files opened + dockWidget->tabWidget()->setElideMode(Qt::ElideNone); + + // We need a unique object name. Can't use the name or file path so use a uuid + dockWidget->setObjectName(QUuid::createUuid().toString()); + + dockWidget->setWidget(editor); + dockWidget->setFeature(ads::CDockWidget::DockWidgetFeature::DockWidgetDeleteOnClose, true); + dockWidget->setFeature(ads::CDockWidget::DockWidgetFeature::CustomCloseHandling, true); + dockWidget->setFeature(ads::CDockWidget::DockWidgetFeature::DockWidgetFloatable, false); + + dockWidget->tabWidget()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(dockWidget->tabWidget(), &QWidget::customContextMenuRequested, this, [=](const QPoint &pos) { + Q_UNUSED(pos) + + emit contextMenuRequestedForEditor(editor); + }); + + // Set the tooltip based on the buffer + if (editor->isFile()) { + dockWidget->tabWidget()->setToolTip(editor->getFilePath()); + } + else { + dockWidget->tabWidget()->setToolTip(editor->getName()); + } + + // Set the icon + if (editor->readOnly()) { + dockWidget->tabWidget()->setIcon(QIcon(":/icons/readonly.png")); + } + else { + dockWidget->tabWidget()->setIcon(QIcon(editor->canSaveToDisk() ? ":/icons/unsaved.png" : ":/icons/saved.png")); + connect(editor, &ScintillaNext::savePointChanged, dockWidget, [=](bool dirty) { + const bool actuallyDirty = editor->canSaveToDisk(); + const QString iconPath = actuallyDirty ? ":/icons/unsaved.png" : ":/icons/saved.png"; + dockWidget->tabWidget()->setIcon(QIcon(iconPath)); + }); + } + + connect(editor, &ScintillaNext::closed, dockWidget, &ads::CDockWidget::closeDockWidget); + connect(editor, &ScintillaNext::closed, this, [=]() { emit editorClosed(editor); }); + connect(editor, &ScintillaNext::renamed, this, [=]() { editorRenamed(editor); }); + + connect(dockWidget, &ads::CDockWidget::closeRequested, this, &DockedEditor::dockWidgetCloseRequested); + + dockManager->addDockWidget(ads::CenterDockWidgetArea, dockWidget, currentDockArea()); + + emit editorAdded(editor); +} + +void DockedEditor::editorRenamed(ScintillaNext *editor) +{ + Q_ASSERT(editor != Q_NULLPTR); + + ads::CDockWidget *dockWidget = qobject_cast(editor->parentWidget()); + + dockWidget->setWindowTitle(editor->getName()); + + if (editor->isFile()) { + dockWidget->tabWidget()->setToolTip(editor->getFilePath()); + } + else { + dockWidget->tabWidget()->setToolTip(editor->getName()); + } +} diff --git a/src/NotepadNext/DockedEditor.h b/src/NotepadNext/DockedEditor.h new file mode 100644 index 000000000..bcaead68c --- /dev/null +++ b/src/NotepadNext/DockedEditor.h @@ -0,0 +1,66 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef DOCKEDEDITOR_H +#define DOCKEDEDITOR_H + +#include + +#include "DockManager.h" +#include "ScintillaNext.h" + +class DockedEditor : public QObject +{ + Q_OBJECT + +private: + ads::CDockManager* dockManager = Q_NULLPTR; + ScintillaNext *currentEditor = Q_NULLPTR; + +public: + explicit DockedEditor(QWidget *parent); + + ScintillaNext *getCurrentEditor() const; + ads::CDockAreaWidget *currentDockArea() const; + + QVector editors() const; + + void switchToEditor(const ScintillaNext *editor); + + int count() const; + +public slots: + void addEditor(ScintillaNext *editor); + +private slots: + void dockWidgetCloseRequested(); + void editorRenamed(ScintillaNext *editor); + +signals: + void editorAdded(ScintillaNext *editor); + void editorCloseRequested(ScintillaNext *editor); + void editorClosed(ScintillaNext *editor); + void editorActivated(ScintillaNext *editor); + void editorOrderChanged(); + + void contextMenuRequestedForEditor(ScintillaNext *editor); + void titleBarDoubleClicked(); +}; + +#endif // DOCKEDEDITOR_H diff --git a/src/NotepadNext/DockedEditorTitleBar.h b/src/NotepadNext/DockedEditorTitleBar.h new file mode 100644 index 000000000..78a407b7f --- /dev/null +++ b/src/NotepadNext/DockedEditorTitleBar.h @@ -0,0 +1,46 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef DOCKEDEDITORTITLEBAR_H +#define DOCKEDEDITORTITLEBAR_H + + +#include + +class DockedEditorTitleBar : public ads::CDockAreaTitleBar +{ + Q_OBJECT + +public: + explicit DockedEditorTitleBar(ads::CDockAreaWidget* parent) : ads::CDockAreaTitleBar(parent) {} + +signals: + void doubleClicked(); + +protected: + void mouseDoubleClickEvent(QMouseEvent *event) { + ads::CDockAreaTitleBar::mouseDoubleClickEvent(event); + + if (event->button() == Qt::LeftButton) { + emit doubleClicked(); + } + } +}; + +#endif // DOCKEDEDITORTITLEBAR_H diff --git a/src/NotepadNext/EditorHexViewerTableModel.cpp b/src/NotepadNext/EditorHexViewerTableModel.cpp new file mode 100644 index 000000000..84d8552e6 --- /dev/null +++ b/src/NotepadNext/EditorHexViewerTableModel.cpp @@ -0,0 +1,146 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "EditorHexViewerTableModel.h" +#include "ScintillaNext.h" + + +static int IndexToPos(const QModelIndex &index) +{ + return index.row() * 16 + index.column(); +} + +EditorHexViewerTableModel::EditorHexViewerTableModel(QObject *parent) + : QAbstractTableModel(parent) +{ +} + +void EditorHexViewerTableModel::setEditor(ScintillaNext *e) +{ + editor = e; +} + +QVariant EditorHexViewerTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::DisplayRole) { + if (orientation == Qt::Horizontal) { + if (section == 16) return QVariant(); + + return QString("%1").arg(section, 2, 16, QChar('0')).toUpper(); + } + else if (orientation == Qt::Vertical) { + return QString("%1").arg(section * 16, 8, 16, QChar('0')).toUpper(); + } + } + else if (role == Qt::TextAlignmentRole) { + return Qt::AlignCenter; + } + + return QVariant(); +} + +int EditorHexViewerTableModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return (editor->length() / 16) + 1; +} + +int EditorHexViewerTableModel::columnCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return 16 + 1; +} + +QVariant EditorHexViewerTableModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole) { + if (index.column() == 16) { + QString str; + + for (int i = 0; i < 16 ; ++i) { + int docPos = index.row() * 16 + i; + if (docPos >= editor->length()) break; + + QChar c = QChar(static_cast(editor->charAt(docPos))); + str += c.isPrint() ? c : '.'; + } + + return str; + } + + int docPos = IndexToPos(index); + if (docPos >= editor->length()) return QVariant(); + + unsigned char ch = static_cast(editor->charAt(docPos)); + return QString("%1").arg(ch, 2, 16, QChar('0')).toUpper(); + } + else if (role == Qt::TextAlignmentRole) { + if (index.column() == 16) return Qt::AlignVCenter; + else return Qt::AlignCenter; + } + + return QVariant(); +} + +bool EditorHexViewerTableModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (index.isValid() && role == Qt::EditRole) { + bool ok; + unsigned int charValue = value.toString().toInt(&ok, 16); + + if (ok && charValue <= 255) { + QByteArray byte(1, static_cast(charValue)); + int pos = IndexToPos(index); + + editor->setTargetRange(pos, pos + 1); + editor->replaceTarget(1, byte.constData()); + + emit dataChanged(index, index, QVector() << role); + + return true; + } + } + + return false; +} + +Qt::ItemFlags EditorHexViewerTableModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + if (index.column() == 16) { + // The string displayed at the end + return Qt::ItemIsEnabled; + } + else if (IndexToPos(index) >= editor->length()) { + // The potentially empty cells past the end of the document + return Qt::NoItemFlags; + } + else { + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; + } +} diff --git a/src/NotepadNext/EditorHexViewerTableModel.h b/src/NotepadNext/EditorHexViewerTableModel.h new file mode 100644 index 000000000..1e0c0af1b --- /dev/null +++ b/src/NotepadNext/EditorHexViewerTableModel.h @@ -0,0 +1,51 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef EDITORHEXVIEWERTABLEMODEL_H +#define EDITORHEXVIEWERTABLEMODEL_H + +#include + + +class ScintillaNext; + +class EditorHexViewerTableModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit EditorHexViewerTableModel(QObject *parent = nullptr); + + void setEditor(ScintillaNext *e); + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + + Qt::ItemFlags flags(const QModelIndex &index) const override; + +private: + ScintillaNext *editor; +}; + +#endif // EDITORHEXVIEWERTABLEMODEL_H diff --git a/src/NotepadNext/EditorManager.cpp b/src/NotepadNext/EditorManager.cpp new file mode 100644 index 000000000..f5236e3a4 --- /dev/null +++ b/src/NotepadNext/EditorManager.cpp @@ -0,0 +1,393 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include + +#include "ApplicationSettings.h" + +#include "EditorManager.h" +#include "ScintillaNext.h" +#include "Scintilla.h" +#include "NotepadNextApplication.h" + +// Editor decorators +#include "BraceMatch.h" +#include "HighlightedScrollBar.h" +#include "SmartHighlighter.h" +#include "SurroundSelection.h" +#include "LineNumbers.h" +#include "BetterMultiSelection.h" +#include "AutoIndentation.h" +#include "AutoCompletion.h" +#include "URLFinder.h" +#include "BookMarkDecorator.h" +#include "ThemeColors.h" + +const int MARK_HIDELINESBEGIN = 23; +const int MARK_HIDELINESEND = 22; +const int MARK_HIDELINESUNDERLINE = 21; + + +EditorManager::EditorManager(ApplicationSettings *settings, QObject *parent) + : QObject(parent), settings(settings) +{ + connect(this, &EditorManager::editorCreated, this, [=](ScintillaNext *editor) { + connect(editor, &ScintillaNext::closed, this, [=]() { + emit editorClosed(editor); + }); + }); + + connect(settings, &ApplicationSettings::showWrapSymbolChanged, this, [=](bool b) { + for (auto &editor : getEditors()) { + editor->setWrapVisualFlags(b ? SC_WRAPVISUALFLAG_END : SC_WRAPVISUALFLAG_NONE); + } + }); + + + connect(settings, &ApplicationSettings::showWhitespaceChanged, this, [=](bool b) { + // TODO: could make SCWS_VISIBLEALWAYS configurable via settings. Probably not worth + // taking up menu space e.g. show all, show leading, show trailing + for (auto &editor : getEditors()) { + editor->setViewWS(b ? SCWS_VISIBLEALWAYS : SCWS_INVISIBLE); + } + }); + + connect(settings, &ApplicationSettings::showEndOfLineChanged, this, [=](bool b) { + for (auto &editor : getEditors()) { + editor->setViewEOL(b); + } + }); + + connect(settings, &ApplicationSettings::showIndentGuideChanged, this, [=](bool b) { + for (auto &editor : getEditors()) { + editor->setIndentationGuides(b ? SC_IV_LOOKBOTH : SC_IV_NONE); + } + }); + + connect(settings, &ApplicationSettings::wordWrapChanged, this, [=](bool b) { + if (b) { + for (auto &editor : getEditors()) { + editor->setWrapMode(SC_WRAP_WORD); + } + } + else { + for (auto &editor : getEditors()) { + // Store the top line and restore it after the lines have been unwrapped + int topLine = editor->docLineFromVisible(editor->firstVisibleLine()); + editor->setWrapMode(SC_WRAP_NONE); + editor->setFirstVisibleLine(topLine); + } + } + }); + + connect(settings, &ApplicationSettings::fontNameChanged, this, [=](QString fontName){ + for (auto &editor : getEditors()) { + for (int i = 0; i <= STYLE_MAX; ++i) { + editor->styleSetFont(i, fontName.toUtf8().data()); + } + } + }); + + connect(settings, &ApplicationSettings::fontSizeChanged, this, [=](int fontSize){ + for (auto &editor : getEditors()) { + for (int i = 0; i <= STYLE_MAX; ++i) { + editor->styleSetSize(i, fontSize); + } + } + }); +} + +ScintillaNext *EditorManager::createEditor(const QString &name) +{ + ScintillaNext *editor = new ScintillaNext(name); + + manageEditor(editor); + + return editor; +} + +ScintillaNext *EditorManager::createEditorFromFile(const QString &filePath, bool tryToCreate) +{ + ScintillaNext *editor = ScintillaNext::fromFile(filePath, tryToCreate); + + if (editor) { + manageEditor(editor); + } + + return editor; +} + +ScintillaNext *EditorManager::getEditorByFilePath(const QString &filePath) +{ + QFileInfo newInfo(filePath); + newInfo.makeAbsolute(); + + purgeOldEditorPointers(); + + for (ScintillaNext *editor : qAsConst(editors)) { + if (editor->isFile() && editor->getFileInfo() == newInfo) { + return editor; + } + } + + return Q_NULLPTR; +} + +void EditorManager::manageEditor(ScintillaNext *editor) +{ + editors.append(QPointer(editor)); + + setupEditor(editor); + + emit editorCreated(editor); +} + +void EditorManager::setupEditor(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + editor->clearCmdKey(SCK_INSERT); + + editor->setFoldMarkers(QStringLiteral("box")); + for (int i = SC_MARKNUM_FOLDEREND; i <= SC_MARKNUM_FOLDEROPEN; ++i) { + editor->markerSetFore(i, 0xF3F3F3); + editor->markerSetBack(i, 0x808080); + editor->markerSetBackSelected(i, 0x0000FF); + } + + editor->setIdleStyling(SC_IDLESTYLING_TOVISIBLE); + editor->setEndAtLastLine(false); + + editor->setMultipleSelection(true); + editor->setAdditionalSelectionTyping(true); + editor->setMultiPaste(SC_MULTIPASTE_EACH); + editor->setVirtualSpaceOptions(SCVS_RECTANGULARSELECTION); + + editor->setMarginLeft(2); + + editor->setMarginWidthN(0, 30); + editor->setMarginMaskN(1, (1<setMarginMaskN(2, SC_MASK_FOLDERS); + editor->setMarginWidthN(2, 14); + + editor->markerDefine(MARK_HIDELINESUNDERLINE, SC_MARK_UNDERLINE); + + + editor->markerDefine(MARK_HIDELINESBEGIN, SC_MARK_ARROW); + editor->markerDefine(MARK_HIDELINESEND, SC_MARK_ARROWDOWN); + + editor->setMarginSensitiveN(2, true); + + editor->setFoldFlags(SC_FOLDFLAG_LINEAFTER_CONTRACTED); + editor->setScrollWidthTracking(true); + editor->setScrollWidth(1); + + editor->setTabDrawMode(SCTD_STRIKEOUT); + editor->setTabWidth(4); + editor->setBackSpaceUnIndents(true); + + editor->setCaretLineVisible(true); + editor->setCaretLineVisibleAlways(true); + editor->setCaretWidth(2); + + editor->setIndentationGuides(SC_IV_LOOKBOTH); + + editor->setAutomaticFold(SC_AUTOMATICFOLD_SHOW | SC_AUTOMATICFOLD_CLICK | SC_AUTOMATICFOLD_CHANGE); + editor->markerEnableHighlight(true); + + editor->setWhitespaceSize(2); + + editor->styleSetSize(STYLE_DEFAULT, settings->fontSize()); + editor->styleSetFont(STYLE_DEFAULT, settings->fontName().toUtf8().data()); + + // set up editor theme (colors + styleClearAll) + setupEditorTheme(editor); + + editor->setCharsDefault(); + editor->setWordChars(editor->wordChars() + settings->additionalWordChars().toLatin1()); + + // STYLE_CONTROLCHAR + // STYLE_CALLTIP + // STYLE_FOLDDISPLAYTEXT + + editor->setViewWS(settings->showWhitespace() ? SCWS_VISIBLEALWAYS : SCWS_INVISIBLE); + editor->setViewEOL(settings->showEndOfLine()); + editor->setWrapVisualFlags(settings->showWrapSymbol() ? SC_WRAPVISUALFLAG_END : SC_WRAPVISUALFLAG_NONE); + editor->setIndentationGuides(settings->showIndentGuide() ? SC_IV_LOOKBOTH : SC_IV_NONE); + editor->setWrapMode(settings->wordWrap() ? SC_WRAP_WORD : SC_WRAP_NONE); + + // Decorators + SmartHighlighter *s = new SmartHighlighter(editor); + s->setEnabled(true); + + HighlightedScrollBarDecorator *h = new HighlightedScrollBarDecorator(editor); + h->setEnabled(true); + + BraceMatch *b = new BraceMatch(editor); + b->setEnabled(true); + + LineNumbers *l = new LineNumbers(editor); + l->setEnabled(true); + + SurroundSelection *ss = new SurroundSelection(editor); + ss->setEnabled(true); + + BetterMultiSelection *bms = new BetterMultiSelection(editor); + bms->setEnabled(true); + + AutoIndentation *ai = new AutoIndentation(editor); + ai->setEnabled(true); + + AutoCompletion *ac = new AutoCompletion(editor); + ac->setEnabled(true); + + URLFinder *uf = new URLFinder(editor); + uf->setEnabled(true); + + BookMarkDecorator *bm = new BookMarkDecorator(editor); + bm->setEnabled(true); +} + +void EditorManager::setupEditorTheme(ScintillaNext *editor) +{ + if (settings->darkMode()) { + editor->setCaretFore(DARK_DEFAULT_FG); + + //editor->setSelFore(true, 0xEFEFEF); + editor->setSelBack(true, 0xA0A0A0); + + // folding/arker + for (int i = SC_MARKNUM_FOLDEREND; i <= SC_MARKNUM_FOLDEROPEN; ++i) { + editor->markerSetFore(i, 0x808080); + editor->markerSetBack(i, 0x1F1F1F); + editor->markerSetBackSelected(i, 0x0000FF); + } + + editor->markerSetBack(MARK_HIDELINESUNDERLINE, invertColor(0x77CC77)); + // end folding/marker + + editor->setEdgeColour(invertColor(0x80FFFF)); + + // https://www.scintilla.org/ScintillaDoc.html#ElementColours + // SC_ELEMENT_SELECTION_TEXT + // SC_ELEMENT_SELECTION_BACK + // SC_ELEMENT_SELECTION_ADDITIONAL_TEXT + // SC_ELEMENT_SELECTION_ADDITIONAL_BACK + // SC_ELEMENT_SELECTION_SECONDARY_TEXT + // SC_ELEMENT_SELECTION_SECONDARY_BACK + // SC_ELEMENT_SELECTION_INACTIVE_TEXT + editor->setElementColour(SC_ELEMENT_SELECTION_INACTIVE_BACK, invertColor(0xFFE0E0E0)); + // SC_ELEMENT_CARET + // SC_ELEMENT_CARET_ADDITIONAL + editor->setElementColour(SC_ELEMENT_CARET_LINE_BACK, 0x606060); + // SC_ELEMENT_WHITE_SPACE + // SC_ELEMENT_WHITE_SPACE_BACK + // setElementColour supports transparency! + editor->setElementColour(SC_ELEMENT_WHITE_SPACE, invertColor(0xFFD0D0D0)); + editor->setElementColour(SC_ELEMENT_WHITE_SPACE_BACK, DARK_DEFAULT_BG); + + // SC_ELEMENT_HOT_SPOT_ACTIVE + // SC_ELEMENT_HOT_SPOT_ACTIVE_BACK + editor->setElementColour(SC_ELEMENT_FOLD_LINE, invertColor(0xFFA0A0A0)); + // SC_ELEMENT_HIDDEN_LINE + + editor->setFoldMarginColour(true, 0x3F3F3F); + editor->setFoldMarginHiColour(true, 0xE9E9E9); + + editor->styleSetFore(STYLE_DEFAULT, DARK_DEFAULT_FG); + editor->styleSetBack(STYLE_DEFAULT, DARK_DEFAULT_BG); + editor->styleClearAll(); + + editor->styleSetFore(STYLE_LINENUMBER, 0xE4E4E4); + editor->styleSetBack(STYLE_LINENUMBER, 0x808080); + + editor->styleSetFore(STYLE_BRACELIGHT, DARK_DEFAULT_FG); + editor->styleSetBack(STYLE_BRACELIGHT, 0x0000FF); + + editor->styleSetFore(STYLE_BRACEBAD, DARK_DEFAULT_FG); + editor->styleSetBack(STYLE_BRACEBAD, 0x000080); + + editor->styleSetFore(STYLE_INDENTGUIDE, 0xC0C0C0); + editor->styleSetBack(STYLE_INDENTGUIDE, DARK_DEFAULT_BG); + } + else { + for (int i = SC_MARKNUM_FOLDEREND; i <= SC_MARKNUM_FOLDEROPEN; ++i) { + editor->markerSetFore(i, 0xF3F3F3); + editor->markerSetBack(i, 0x808080); + editor->markerSetBackSelected(i, 0x0000FF); + } + + editor->markerSetBack(MARK_HIDELINESUNDERLINE, 0x77CC77); + editor->setEdgeColour(0x80FFFF); + + // https://www.scintilla.org/ScintillaDoc.html#ElementColours + // SC_ELEMENT_SELECTION_TEXT + // SC_ELEMENT_SELECTION_BACK + // SC_ELEMENT_SELECTION_ADDITIONAL_TEXT + // SC_ELEMENT_SELECTION_ADDITIONAL_BACK + // SC_ELEMENT_SELECTION_SECONDARY_TEXT + // SC_ELEMENT_SELECTION_SECONDARY_BACK + // SC_ELEMENT_SELECTION_INACTIVE_TEXT + editor->setElementColour(SC_ELEMENT_SELECTION_INACTIVE_BACK, 0xFFE0E0E0); + // SC_ELEMENT_CARET + // SC_ELEMENT_CARET_ADDITIONAL + editor->setElementColour(SC_ELEMENT_CARET_LINE_BACK, 0xFFFFE8E8); + editor->setElementColour(SC_ELEMENT_WHITE_SPACE, 0xFFD0D0D0); + // SC_ELEMENT_WHITE_SPACE_BACK + // SC_ELEMENT_HOT_SPOT_ACTIVE + // SC_ELEMENT_HOT_SPOT_ACTIVE_BACK + editor->setElementColour(SC_ELEMENT_FOLD_LINE, 0xFFA0A0A0); + // SC_ELEMENT_HIDDEN_LINE + + editor->setFoldMarginColour(true, WHITE); + editor->setFoldMarginHiColour(true, 0xE9E9E9); + + editor->styleSetFore(STYLE_DEFAULT, LIGHT_DEFAULT_FG); + editor->styleSetBack(STYLE_DEFAULT, LIGHT_DEFAULT_BG); + editor->styleClearAll(); + + editor->styleSetFore(STYLE_LINENUMBER, 0x808080); + editor->styleSetBack(STYLE_LINENUMBER, 0xE4E4E4); + + editor->styleSetFore(STYLE_BRACELIGHT, 0x0000FF); + editor->styleSetBack(STYLE_BRACELIGHT, LIGHT_DEFAULT_BG); + + editor->styleSetFore(STYLE_BRACEBAD, 0x000080); + editor->styleSetBack(STYLE_BRACEBAD, LIGHT_DEFAULT_BG); + + editor->styleSetFore(STYLE_INDENTGUIDE, 0xC0C0C0); + editor->styleSetBack(STYLE_INDENTGUIDE, LIGHT_DEFAULT_BG); + } +} + +void EditorManager::purgeOldEditorPointers() +{ + QMutableListIterator> it(editors); + + while (it.hasNext()) { + QPointer pointer = it.next(); + if (pointer.isNull()) + it.remove(); + } +} + +QList > EditorManager::getEditors() +{ + purgeOldEditorPointers(); + return editors; +} diff --git a/src/NotepadNext/EditorManager.h b/src/NotepadNext/EditorManager.h new file mode 100644 index 000000000..210fb3501 --- /dev/null +++ b/src/NotepadNext/EditorManager.h @@ -0,0 +1,58 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef EDITORMANAGER_H +#define EDITORMANAGER_H + +#include +#include + + +class ApplicationSettings; +class ScintillaNext; + +class EditorManager : public QObject +{ + Q_OBJECT + +public: + explicit EditorManager(ApplicationSettings *settings, QObject *parent = nullptr); + + ScintillaNext *createEditor(const QString &name); + ScintillaNext *createEditorFromFile(const QString &filePath, bool tryToCreate=false); + + ScintillaNext *getEditorByFilePath(const QString &filePath); + + void manageEditor(ScintillaNext *editor); + +signals: + void editorCreated(ScintillaNext *editor); + void editorClosed(ScintillaNext *editor); + +private: + void setupEditor(ScintillaNext *editor); + void setupEditorTheme(ScintillaNext *editor); + void purgeOldEditorPointers(); + QList> getEditors(); + + QList> editors; + ApplicationSettings *settings; +}; + +#endif // EDITORMANAGER_H diff --git a/src/NotepadNext/EditorPrintPreviewRenderer.cpp b/src/NotepadNext/EditorPrintPreviewRenderer.cpp new file mode 100644 index 000000000..7d0d51d51 --- /dev/null +++ b/src/NotepadNext/EditorPrintPreviewRenderer.cpp @@ -0,0 +1,70 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "EditorPrintPreviewRenderer.h" +#include "ScintillaNext.h" + +#include +#include +#include + +EditorPrintPreviewRenderer::EditorPrintPreviewRenderer(ScintillaNext *editor) + : QObject(), editor(editor) +{ +} + +void EditorPrintPreviewRenderer::render(QPrinter *printer) +{ + QRectF printableArea(QPointF(0, 0), printer->pageRect(QPrinter::DevicePixel).size()); + + qInfo() << "Print from page" << printer->fromPage() << "to" << printer->toPage(); + qInfo() << "Paper:" << printer->paperRect(QPrinter::DevicePixel); + qInfo() << "Page:" << printer->pageRect(QPrinter::DevicePixel); + qInfo() << "Printable Area:" << printableArea; + + const int fromPage = printer->fromPage(); + const int toPage = printer->toPage(); + + // The printer starts with a valid page initially + bool needsNewPage = false; + + int startPos = 0; + int pageNum = 1; + + QPainter painter(printer); + + do { + bool needsToDraw = (fromPage == 0 && toPage == 0) || (fromPage <= pageNum && pageNum <= toPage); + + if (needsToDraw) { + if (needsNewPage) { + printer->newPage(); + } + else { + needsNewPage = true; + } + } + + startPos = editor->formatRange(needsToDraw, printer, printer, + printableArea.toRect(), printer->paperRect(QPrinter::DevicePixel).toRect(), + startPos, editor->length()); + + pageNum++; + } while (startPos < editor->length()); +} diff --git a/src/NotepadNext/EditorPrintPreviewRenderer.h b/src/NotepadNext/EditorPrintPreviewRenderer.h new file mode 100644 index 000000000..c3bd5715e --- /dev/null +++ b/src/NotepadNext/EditorPrintPreviewRenderer.h @@ -0,0 +1,43 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef EDITORPRINTPREVIEWRENDERER_H +#define EDITORPRINTPREVIEWRENDERER_H + +#include + + +class ScintillaNext; +class QPrinter; + +class EditorPrintPreviewRenderer : public QObject +{ + Q_OBJECT + +public: + explicit EditorPrintPreviewRenderer(ScintillaNext *editor); + +public slots: + void render(QPrinter *printer); + +private: + ScintillaNext *editor; +}; + +#endif // EDITORPRINTPREVIEWRENDERER_H diff --git a/src/NotepadNext/FadingIndicator.cpp b/src/NotepadNext/FadingIndicator.cpp new file mode 100644 index 000000000..143aafa80 --- /dev/null +++ b/src/NotepadNext/FadingIndicator.cpp @@ -0,0 +1,159 @@ +/* + * This file is part of Notepad Next. + * Copyright (C) 2016 The Qt Company Ltd. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "FadingIndicator.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Internal { + +class FadingIndicatorPrivate : public QWidget +{ + Q_OBJECT + +public: + FadingIndicatorPrivate(QWidget *parent, FadingIndicator::TextSize size) + : QWidget(parent) + { + setAttribute(Qt::WA_TransparentForMouseEvents, true); + m_effect = new QGraphicsOpacityEffect(this); + setGraphicsEffect(m_effect); + m_effect->setOpacity(.999); + + m_label = new QLabel; + QFont font = m_label->font(); + font.setPixelSize(size == FadingIndicator::LargeText ? 30 : 18); + m_label->setFont(font); + QPalette pal = palette(); + pal.setColor(QPalette::WindowText, pal.color(QPalette::Window)); + m_label->setPalette(pal); + auto layout = new QHBoxLayout; + setLayout(layout); + layout->addWidget(m_label); + } + + void setText(const QString &text) + { + m_pixmap = QPixmap(); + m_label->setText(text); + m_effect->setOpacity(.6); // because of the fat opaque background color + layout()->setSizeConstraint(QLayout::SetFixedSize); + adjustSize(); + QWidget *parent = parentWidget(); + QPoint pos = parent ? (parent->rect().center() - rect().center()) : QPoint(); + if (pixmapIndicator && pixmapIndicator->geometry().intersects(QRect(pos, size()))) + pos.setY(pixmapIndicator->geometry().bottom() + 1); + move(pos); + } + + void setPixmap(const QString &uri) + { + m_label->hide(); + m_pixmap.load(uri); + layout()->setSizeConstraint(QLayout::SetNoConstraint); + resize(m_pixmap.size() / m_pixmap.devicePixelRatio()); + QWidget *parent = parentWidget(); + QPoint pos = parent ? (parent->rect().center() - rect().center()) : QPoint(); + if (textIndicator && textIndicator->geometry().intersects(QRect(pos, size()))) + pos.setY(textIndicator->geometry().bottom() + 1); + move(pos); + } + + void run(int ms) + { + show(); + raise(); + QTimer::singleShot(ms, this, &FadingIndicatorPrivate::runInternal); + } + + static QPointer textIndicator; + static QPointer pixmapIndicator; + +protected: + void paintEvent(QPaintEvent *) override + { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + if (!m_pixmap.isNull()) { + p.drawPixmap(rect(), m_pixmap); + } else { + p.setBrush(palette().color(QPalette::WindowText)); + p.setPen(Qt::NoPen); + p.drawRoundedRect(rect(), 15, 15); + } + } + +private: + void runInternal() + { + QPropertyAnimation *anim = new QPropertyAnimation(m_effect, "opacity", this); + anim->setDuration(200); + anim->setEndValue(0.); + connect(anim, &QAbstractAnimation::finished, this, &QObject::deleteLater); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + + QGraphicsOpacityEffect *m_effect; + QLabel *m_label; + QPixmap m_pixmap; +}; + +QPointer FadingIndicatorPrivate::textIndicator; +QPointer FadingIndicatorPrivate::pixmapIndicator; + +} // Internal + + +namespace FadingIndicator { + +void showText(QWidget *parent, const QString &text, TextSize size) +{ + QPointer &indicator = Internal::FadingIndicatorPrivate::textIndicator; + + if (indicator) + delete indicator; + + indicator = new Internal::FadingIndicatorPrivate(parent, size); + indicator->setText(text); + indicator->run(2500); // deletes itself +} + +void showPixmap(QWidget *parent, const QString &pixmap) +{ + QPointer &indicator = Internal::FadingIndicatorPrivate::pixmapIndicator; + + if (indicator) + delete indicator; + + indicator = new Internal::FadingIndicatorPrivate(parent, LargeText); + indicator->setPixmap(pixmap); + indicator->run(300); // deletes itself +} + +} + +#include "FadingIndicator.moc" diff --git a/src/NotepadNext/FadingIndicator.h b/src/NotepadNext/FadingIndicator.h new file mode 100644 index 000000000..540f102ee --- /dev/null +++ b/src/NotepadNext/FadingIndicator.h @@ -0,0 +1,34 @@ +/* + * This file is part of Notepad Next. + * Copyright (C) 2016 The Qt Company Ltd. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#pragma once + +#include + +namespace FadingIndicator { + +enum TextSize { + SmallText, + LargeText +}; + +void showText(QWidget *parent, const QString &text, TextSize size = LargeText); +void showPixmap(QWidget *parent, const QString &pixmap); + +} diff --git a/src/NotepadNext/FileDialogHelpers.cpp b/src/NotepadNext/FileDialogHelpers.cpp new file mode 100644 index 000000000..3455bca00 --- /dev/null +++ b/src/NotepadNext/FileDialogHelpers.cpp @@ -0,0 +1,94 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "FileDialogHelpers.h" + + +/* + * NOTE: This code is nearly identical to the QFileDialog implementation of several static methods. + * Since the QDir filter options were not exposed, there was no way to specify QDir::Hidden. + */ + + +constexpr QDir::Filters default_filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files | QDir::Hidden; + + +QList FileDialogHelpers::getOpenFileUrls(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes) +{ + QFileDialog dialog(parent, caption, dir, filter); + + dialog.setSupportedSchemes(supportedSchemes); + dialog.setFilter(default_filters); + dialog.setOptions(options); + dialog.setFileMode(QFileDialog::ExistingFiles); + + if (selectedFilter && !selectedFilter->isEmpty()) + dialog.selectNameFilter(*selectedFilter); + if (dialog.exec() == QDialog::Accepted) { + if (selectedFilter) + *selectedFilter = dialog.selectedNameFilter(); + return dialog.selectedUrls(); + } + return QList(); +} + +QStringList FileDialogHelpers::getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) +{ + const QStringList schemes = QStringList(QStringLiteral("file")); + const QList selectedUrls = getOpenFileUrls(parent, caption, dir, filter, selectedFilter, options, schemes); + QStringList fileNames; + + fileNames.reserve(selectedUrls.size()); + for (const QUrl &url : selectedUrls) { + if (url.isLocalFile() || url.isEmpty()) + fileNames << url.toLocalFile(); + else + fileNames << url.toString(); + } + return fileNames; +} + +QUrl FileDialogHelpers::getSaveFileUrl(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes) +{ + QFileDialog dialog(parent, caption, dir, filter); + + dialog.setSupportedSchemes(supportedSchemes); + dialog.setAcceptMode(QFileDialog::AcceptSave); + dialog.setFilter(default_filters); + dialog.setOptions(options); + + if (selectedFilter && !selectedFilter->isEmpty()) + dialog.selectNameFilter(*selectedFilter); + if (dialog.exec() == QDialog::Accepted) { + if (selectedFilter) + *selectedFilter = dialog.selectedNameFilter(); + return dialog.selectedUrls().value(0); + } + return QUrl(); +} + +QString FileDialogHelpers::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) +{ + const QStringList schemes = QStringList(QStringLiteral("file")); + const QUrl selectedUrl = getSaveFileUrl(parent, caption, dir, filter, selectedFilter, options, schemes); + if (selectedUrl.isLocalFile() || selectedUrl.isEmpty()) + return selectedUrl.toLocalFile(); + else + return selectedUrl.toString(); +} diff --git a/src/NotepadNext/FileDialogHelpers.h b/src/NotepadNext/FileDialogHelpers.h new file mode 100644 index 000000000..a4b3f07b6 --- /dev/null +++ b/src/NotepadNext/FileDialogHelpers.h @@ -0,0 +1,35 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef FILEDIALOGHELPERS_H +#define FILEDIALOGHELPERS_H + +#include +#include + +namespace FileDialogHelpers +{ + QList getOpenFileUrls(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes); + QStringList getOpenFileNames(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = QFileDialog::Options()); + + QUrl getSaveFileUrl(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, const QStringList &supportedSchemes); + QString getSaveFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = QFileDialog::Options()); +} + +#endif // FILEDIALOGHELPERS_H diff --git a/src/NotepadNext/Finder.cpp b/src/NotepadNext/Finder.cpp new file mode 100644 index 000000000..fe5d3e0b3 --- /dev/null +++ b/src/NotepadNext/Finder.cpp @@ -0,0 +1,183 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "Finder.h" +#include "UndoAction.h" + +Finder::Finder(ScintillaNext *edit) : + editor(edit) +{ + search_flags = editor->searchFlags(); +} + +void Finder::setEditor(ScintillaNext *editor) +{ + this->editor = editor; +} + +void Finder::setSearchFlags(int flags) +{ + this->search_flags = flags; +} + +void Finder::setWrap(bool wrap) +{ + this->wrap = wrap; +} + +void Finder::setSearchText(const QString &text) +{ + this->text = text; +} + +Sci_CharacterRange Finder::findNext(int startPos) +{ + did_latest_search_wrap = false; + + if (text.isEmpty()) + return {INVALID_POSITION, INVALID_POSITION}; + + const int pos = startPos == INVALID_POSITION ? editor->selectionEnd() : startPos; + const QByteArray textData = text.toUtf8(); + + editor->setTargetRange(pos, editor->length()); + editor->setSearchFlags(search_flags); + + if (editor->searchInTarget(textData.length(), textData.constData()) != INVALID_POSITION) { + return {static_cast(editor->targetStart()), static_cast(editor->targetEnd())}; + } + else if (wrap) { + editor->setTargetRange(0, pos); + if (editor->searchInTarget(textData.length(), textData.constData()) != INVALID_POSITION) { + did_latest_search_wrap = true; + + return {static_cast(editor->targetStart()), static_cast(editor->targetEnd())}; + } + } + + return {INVALID_POSITION, INVALID_POSITION}; +} + +Sci_CharacterRange Finder::findPrev() +{ + did_latest_search_wrap = false; + + if (text.isEmpty()) + return {INVALID_POSITION, INVALID_POSITION}; + + const int pos = editor->selectionStart(); + const QByteArray textData = text.toUtf8(); + + editor->setTargetRange(pos, editor->length()); + editor->setSearchFlags(search_flags); + + auto range = editor->findText(editor->searchFlags(), textData.constData(), pos, 0); + + if (range.first != INVALID_POSITION) { + return {static_cast(range.first), static_cast(range.second)}; + } + else if (wrap) { + range = editor->findText(editor->searchFlags(), textData.constData(), editor->length(), pos); + if (range.first != INVALID_POSITION) { + did_latest_search_wrap = true; + + return {static_cast(range.first), static_cast(range.second)}; + } + } + + return {INVALID_POSITION, INVALID_POSITION}; +} + +// Count all occurrences in the document +int Finder::count() +{ + int total = 0; + + if (text.length() > 0) { + forEachMatch([&](int start, int end) { + Q_UNUSED(start); + total++; + return end; + }); + } + + return total; +} + +Sci_CharacterRange Finder::replaceSelectionIfMatch(const QString &replaceText) +{ + const QByteArray textData = text.toUtf8(); + bool isRegex = editor->searchFlags() & SCFIND_REGEXP; + + // Search just in the selection to see if the current selection is a match + editor->setTargetStart(editor->selectionStart()); + editor->setTargetEnd(editor->selectionEnd()); + editor->setSearchFlags(search_flags); + + if (editor->searchInTarget(textData.length(), textData.constData()) != INVALID_POSITION) { + const QByteArray replaceData = replaceText.toUtf8(); + + if (isRegex) + editor->replaceTargetRE(replaceData.length(), replaceData.constData()); + else + editor->replaceTarget(replaceData.length(), replaceData.constData()); + + return {static_cast(editor->targetStart()), static_cast(editor->targetEnd())}; + } + + return {INVALID_POSITION, INVALID_POSITION}; +} + +int Finder::replaceAll(const QString &replaceText) +{ + if (text.isEmpty()) + return 0; + + const QByteArray &replaceData = replaceText.toUtf8(); + const QByteArray &b = text.toUtf8(); + const char *c = b.constData(); + Sci_TextToFind ttf {{0, (Sci_PositionCR)editor->length()}, c, {-1, -1}}; + const bool isRegex = search_flags & SCFIND_REGEXP; + int total = 0; + + // Don't technically need to set the search flags here but do it just in case something looks at the search flags later + editor->setSearchFlags(search_flags); + + // NOTE: can't use editor->forEachMatch() here since the search range can grow since the document is changing + + const UndoAction ua(editor); + while (editor->send(SCI_FINDTEXT, search_flags, reinterpret_cast(&ttf)) != -1) { + const int start = ttf.chrgText.cpMin; + const int end = ttf.chrgText.cpMax; + + editor->setTargetRange(start, end); + + if (isRegex) + ttf.chrg.cpMin = start + editor->replaceTargetRE(replaceData.length(), replaceData.constData()); + else + ttf.chrg.cpMin = start + editor->replaceTarget(replaceData.length(), replaceData.constData()); + + // The replace could have changed the document size, so update the end of the search range + ttf.chrg.cpMax = editor->length(); + + total++; + } + + return total; +} diff --git a/src/NotepadNext/Finder.h b/src/NotepadNext/Finder.h new file mode 100644 index 000000000..4f091eb0c --- /dev/null +++ b/src/NotepadNext/Finder.h @@ -0,0 +1,67 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef FINDER_H +#define FINDER_H + +#include "ScintillaNext.h" + +class Finder +{ +public: + explicit Finder(ScintillaNext *edit); + + void setEditor(ScintillaNext *editor); + void setSearchFlags(int flags); + void setWrap(bool wrap); + void setSearchText(const QString &text); + + Sci_CharacterRange findNext(int startPos = INVALID_POSITION); + Sci_CharacterRange findPrev(); + int count(); + + bool didLatestSearchWrapAround() const { return did_latest_search_wrap; } + + Sci_CharacterRange replaceSelectionIfMatch(const QString &replaceText); + int replaceAll(const QString &replaceText); + + template + void forEachMatch(Func callback) { forEachMatchInRange(callback, {0, (Sci_PositionCR)editor->length()}); } + + template + void forEachMatchInRange(Func callback, Sci_CharacterRange range); + +private: + ScintillaNext *editor; + bool did_latest_search_wrap = false; + + bool wrap = false; + int search_flags = 0; + QString text; +}; + + +template +void Finder::forEachMatchInRange(Func callback, Sci_CharacterRange range) +{ + editor->setSearchFlags(search_flags); + editor->forEachMatchInRange(text.toUtf8(), callback, range); +} + +#endif // FINDER_H diff --git a/src/NotepadNext/FocusWatcher.h b/src/NotepadNext/FocusWatcher.h new file mode 100644 index 000000000..7f9ffc985 --- /dev/null +++ b/src/NotepadNext/FocusWatcher.h @@ -0,0 +1,58 @@ +/* + * This file is part of Notepad Next. + * Copyright 2020 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef FOCUSWATCHER_H +#define FOCUSWATCHER_H + +#include +#include + + +class FocusWatcher : public QObject { + Q_OBJECT + +public: + explicit FocusWatcher(QObject* parent = nullptr) : QObject(parent) { + if (parent) + parent->installEventFilter(this); + } + + protected: + bool eventFilter(QObject *obj, QEvent *event) override { + Q_UNUSED(obj) + + if (event->type() == QEvent::FocusIn) { + emit focusChanged(true); + emit focusIn(); + } + else if (event->type() == QEvent::FocusOut) { + emit focusChanged(false); + emit focusOut(); + } + + return false; + } + +signals: + void focusChanged(bool in); + void focusIn(); + void focusOut(); +}; + +#endif // FOCUSWATCHER_H diff --git a/src/NotepadNext/HtmlConverter.cpp b/src/NotepadNext/HtmlConverter.cpp new file mode 100644 index 000000000..722dc7dbb --- /dev/null +++ b/src/NotepadNext/HtmlConverter.cpp @@ -0,0 +1,137 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "HtmlConverter.h" + +#include +#include + + +static QByteArray ScintillaColorToCssColor(int color) +{ + int r = color & 0xFF; + int g = (color >> 8) & 0xFF; + int b = (color >> 16) & 0xFF; + + return QStringLiteral("rgb(%1, %2, %3)").arg(r).arg(g).arg(b).toLatin1(); +} + +static void StyleToCss(QTextStream &stream, ScintillaNext *editor, int style) +{ + stream << ".s" << style << " {" << Qt::endl; + stream << " font-family: '" << editor->styleFont(style) << "';" << Qt::endl; + stream << " font-size: " << editor->styleSize(style) << "pt;" << Qt::endl; + stream << " color: " << ScintillaColorToCssColor(editor->styleFore(style)) << ";" << Qt::endl; + stream << " background: " << ScintillaColorToCssColor(editor->styleBack(style)) << ";" << Qt::endl; + + if (editor->styleBold(style)) + stream << " font-weight: bold;" << Qt::endl; + + if (editor->styleItalic(style)) + stream << " font-style: italic;" << Qt::endl; + + if (editor->styleUnderline(style)) + stream << " text-decoration: underline;" << Qt::endl; + + stream << "}" << Qt::endl; +} + +static void AddCharEscaped(QTextStream &stream, int ch) +{ + switch (ch) { + case '<': + stream << QByteArrayLiteral("<"); + break; + case '>': + stream << QByteArrayLiteral(">"); + break; + case '&': + stream << QByteArrayLiteral("&"); + break; + default: + stream << static_cast(ch); + } +} + +void HtmlConverter::convertRange(QTextStream &stream, int start, int end) +{ + ensureDocumentStyled(start, end); + + // Create the raw html and keep track of the used styles + QByteArray html; + QTextStream html_stream(&html); + QSet usedStyles; + int currentStyle = -1; + + for (int i = start; i < end; ++i) { + int style = editor->styleAt(i); + + if (style != currentStyle) { + currentStyle = style; + usedStyles.insert(currentStyle); + + html_stream << ""; + } + + const int ch = editor->charAt(i); + if (ch == '\r'){ + if (editor->charAt(i + 1) != '\n') { + AddCharEscaped(html_stream, ch); + } + } + else { + AddCharEscaped(html_stream, ch); + } + } + html_stream.flush(); + + + // Generate the CSS for just the styles that were used + QByteArray css; + QTextStream css_stream(&css); + for (const int style : usedStyles) { + StyleToCss(css_stream, editor, style); + } + css_stream.flush(); + + + // Generate the entire document + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream << "Exported from Notepad Next" << Qt::endl; + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream << "
"; + stream << html; + stream << "
" << Qt::endl; + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream << "" << Qt::endl; + stream.flush(); +} diff --git a/src/NotepadNext/HtmlConverter.h b/src/NotepadNext/HtmlConverter.h new file mode 100644 index 000000000..34d561bee --- /dev/null +++ b/src/NotepadNext/HtmlConverter.h @@ -0,0 +1,31 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + +#include "Converter.h" + +class HtmlConverter : public Converter +{ + using Converter::Converter; + +public: + void convertRange(QTextStream &stream, int start, int end) override; +}; + diff --git a/src/NotepadNext/IFaceTable.cpp b/src/NotepadNext/IFaceTable.cpp new file mode 100644 index 000000000..b30427756 --- /dev/null +++ b/src/NotepadNext/IFaceTable.cpp @@ -0,0 +1,175 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "IFaceTable.h" +#include +#include +#include +#include + +template +typename std::iterator_traits::value_type const *binary_find(Iter begin, Iter end, const char *name) { + auto it = std::lower_bound(begin, end, name, [](const auto &lhs, const char *rhs) { + return strcmp(lhs.name, rhs) < 0; + }); + + if (it == end || strcmp(name, it->name) != 0) { + return nullptr; + } + else { + return &(*it); + } +} + +const IFaceConstant *IFaceTable::FindConstant(const char *name) const { + return binary_find(constants.cbegin(), constants.cend(), name); +} + +const IFaceFunction *IFaceTable::FindFunction(const char *name) const { + return binary_find(functions.cbegin(), functions.cend(), name); +} + +const IFaceFunction *IFaceTable::FindFunctionByConstantName(const char *name) const { + if (strncmp(name, prefix, strlen(prefix)) == 0) { + // This looks like a constant for an iface function. This requires + // a sequential search. Take special care since the function names + // are mixed case, whereas the constants are all-caps. + + for (const auto &func : functions) { + const char *nm = name + strlen(prefix); + const char *fn = func.name; + while (*nm && *fn && (*nm == toupper(*fn))) { + ++nm; + ++fn; + } + if (!*nm && !*fn) { + return &func; + } + } + } + return nullptr; +} + +const IFaceFunction *IFaceTable::FindFunctionByValue(int value) const { + for (const auto &func : functions) { + if (func.value == value) + return &func; + } + return nullptr; +} + +const IFaceProperty *IFaceTable::FindProperty(const char *name) const { + return binary_find(properties.cbegin(), properties.cend(), name); +} + +int IFaceTable::GetConstantName(int value, char *nameOut, unsigned nameBufferLen, const char *hint) const { + if (nameOut && nameBufferLen > 0) { + *nameOut = '\0'; + } + + // Look in both the constants table and the functions table. Start with functions. + for (const auto &func : functions) { + if (func.value == value) { + int len = static_cast(strlen(func.name) + strlen(prefix)); + if (nameOut && (static_cast(nameBufferLen) > len)) { + strcpy(nameOut, prefix); + strcat(nameOut, func.name); + // fix case + for (char *nm = nameOut + strlen(prefix); *nm; ++nm) { + if (*nm >= 'a' && *nm <= 'z') { + *nm = static_cast(*nm - 'a' + 'A'); + } + } + return len; + } else { + return -1 - len; + } + } + } + + for (const auto &con : constants) { + if (con.value == value && (hint == NULL || strncmp(hint, con.name, strlen(hint)) == 0)) { + int len = static_cast(strlen(con.name)); + if (nameOut && (static_cast(nameBufferLen) > len)) { + strcpy(nameOut, con.name); + return len; + } else { + return -1 - len; + } + } + } + + return 0; +} + +const IFaceFunction *IFaceTable::GetFunctionByMessage(int message) const { + for (const auto &func : functions) { + if (func.value == message) { + return &func; + } + } + return nullptr; +} + +IFaceFunction IFaceTable::GetPropertyFuncByMessage(int message) const { + for (const auto &prop : properties) { + if (prop.getter == message) { + return prop.GetterFunction(); + } + else if (prop.setter == message) { + return prop.SetterFunction(); + } + } + return { "invalid", -1, iface_void, {iface_void, iface_void} }; +} + +std::vector IFaceTable::GetAllConstantNames() const { + std::vector kws; + std::string prefix_str(prefix); + + kws.reserve(constants.size() + functions.size()); + + std::transform(constants.begin(), constants.end(), std::back_inserter(kws), [](const IFaceConstant &ifc) { return ifc.name; }); + std::transform(functions.begin(), functions.end(), std::back_inserter(kws), [&](const IFaceFunction &iff) { + std::string s = prefix_str + std::string(iff.name); + std::transform(s.begin(), s.end(), s.begin(), ::toupper); + return s; + }); + + std::sort(kws.begin(), kws.end()); + return kws; +} + +std::vector IFaceTable::GetAllFunctionNames() const { + std::vector kws; + + kws.reserve(functions.size()); + std::transform(functions.begin(), functions.end(), std::back_inserter(kws), [](const IFaceFunction &iff) { return iff.name; }); + + return kws; +} + +std::vector IFaceTable::GetAllPropertyNames() const { + std::vector kws; + + kws.reserve(properties.size()); + std::transform(properties.begin(), properties.end(), std::back_inserter(kws), [](const IFaceProperty &ifp) { return ifp.name; }); + + return kws; +} diff --git a/src/NotepadNext/IFaceTable.h b/src/NotepadNext/IFaceTable.h new file mode 100644 index 000000000..b6e81efd9 --- /dev/null +++ b/src/NotepadNext/IFaceTable.h @@ -0,0 +1,149 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef IFACETABLE_H +#define IFACETABLE_H + +#include +#include + +enum IFaceType { + iface_void, + iface_int, + iface_length, + iface_position, + iface_colour, + iface_bool, + iface_keymod, + iface_string, + iface_stringresult, + iface_cells, // This and everything else below is not "scriptable" + iface_textrange, + iface_findtext, + iface_formatrange +}; + +struct IFaceConstant { + const char *name; + int value; +}; + +struct IFaceFunction { + const char *name; + int value; + IFaceType returnType; + IFaceType paramType[2]; +}; + +struct IFaceProperty { + const char *name; + int getter; + int setter; + IFaceType valueType; + IFaceType paramType; + + IFaceFunction GetterFunction() const { + IFaceFunction result = {"(property getter)",getter,valueType,{paramType,iface_void}}; + return result; + } + + IFaceFunction SetterFunction() const { + IFaceFunction result = {"(property setter)",setter,iface_void,{valueType, iface_void}}; + if (paramType != iface_void) { + result.paramType[0] = paramType; + if (valueType == iface_stringresult) + result.paramType[1] = iface_string; + else + result.paramType[1] = valueType; + } + if ((paramType == iface_void) && ((valueType == iface_string) || (valueType == iface_stringresult))) { + result.paramType[0] = paramType; + if (valueType == iface_stringresult) + result.paramType[1] = iface_string; + else + result.paramType[1] = valueType; + } + + return result; + } +}; + +inline bool IFaceTypeIsScriptable(IFaceType t, int index) { + return t < iface_stringresult || (index == 1 && t == iface_stringresult); +} + +inline bool IFaceTypeIsNumeric(IFaceType t) { + return (t > iface_void && t < iface_bool); +} + +inline bool IFaceFunctionIsScriptable(const IFaceFunction &f) { + return IFaceTypeIsScriptable(f.paramType[0], 0) && IFaceTypeIsScriptable(f.paramType[1], 1); +} + +inline bool IFacePropertyIsScriptable(const IFaceProperty &p) { + return (((p.valueType > iface_void) && (p.valueType <= iface_stringresult) && (p.valueType != iface_keymod)) && + ((p.paramType < iface_colour) || (p.paramType == iface_string) || (p.paramType == iface_bool)) && (p.getter || p.setter)); +} + +class IFaceTableInterface { +public: + virtual const IFaceConstant *FindConstant(const char *name) const = 0; + virtual const IFaceFunction *FindFunction(const char *name) const = 0; + virtual const IFaceFunction *FindFunctionByConstantName(const char *name) const = 0; + virtual const IFaceFunction *FindFunctionByValue(int value) const = 0; + virtual const IFaceProperty *FindProperty(const char *name) const = 0; + virtual int GetConstantName(int value, char *nameOut, unsigned nameBufferLen, const char *hint) const = 0; + virtual const IFaceFunction *GetFunctionByMessage(int message) const = 0; + virtual IFaceFunction GetPropertyFuncByMessage(int message) const = 0; +}; + +class IFaceTable : public IFaceTableInterface { +public: + IFaceTable(const char *_prefix, + const std::vector &_functions, + const std::vector &_constants, + const std::vector &_properties) : + prefix(_prefix), + functions(_functions), + constants(_constants), + properties(_properties) + {} + + const char *prefix; + + const std::vector &functions; + const std::vector &constants; + const std::vector &properties; + + // IFaceTableInterface + const IFaceConstant *FindConstant(const char *name) const; + const IFaceFunction *FindFunction(const char *name) const; + const IFaceFunction *FindFunctionByConstantName(const char *name) const; + const IFaceFunction *FindFunctionByValue(int value) const; + const IFaceProperty *FindProperty(const char *name) const; + int GetConstantName(int value, char *nameOut, unsigned nameBufferLen, const char *hint) const; + const IFaceFunction *GetFunctionByMessage(int message) const; + IFaceFunction GetPropertyFuncByMessage(int message) const; + + std::vector GetAllConstantNames() const; + std::vector GetAllFunctionNames() const; + std::vector GetAllPropertyNames() const; +}; + +#endif diff --git a/src/NotepadNext/IFaceTableMixer.cpp b/src/NotepadNext/IFaceTableMixer.cpp new file mode 100644 index 000000000..9f6f7a646 --- /dev/null +++ b/src/NotepadNext/IFaceTableMixer.cpp @@ -0,0 +1,84 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "IFaceTableMixer.h" + +const IFaceConstant *IFaceTableMixer::FindConstant(const char *name) const { + for (auto const &iface : ifaces) { + const IFaceConstant *ret = iface->FindConstant(name); + if (ret != nullptr) return ret; + } + return nullptr; +} + +const IFaceFunction *IFaceTableMixer::FindFunction(const char *name) const { + for (auto const &iface : ifaces) { + const IFaceFunction *ret = iface->FindFunction(name); + if (ret != nullptr) return ret; + } + return nullptr; +} + +const IFaceFunction *IFaceTableMixer::FindFunctionByConstantName(const char *name) const { + for (auto const &iface : ifaces) { + const IFaceFunction *ret = iface->FindFunctionByConstantName(name); + if (ret != nullptr) return ret; + } + return nullptr; +} + +const IFaceFunction *IFaceTableMixer::FindFunctionByValue(int value) const { + for (auto const &iface : ifaces) { + const IFaceFunction *ret = iface->FindFunctionByValue(value); + if (ret != nullptr) return ret; + } + return nullptr; +} + +const IFaceProperty *IFaceTableMixer::FindProperty(const char *name) const { + for (auto const &iface : ifaces) { + const IFaceProperty *ret = iface->FindProperty(name); + if (ret != nullptr) return ret; + } + return nullptr; +} + +int IFaceTableMixer::GetConstantName(int value, char *nameOut, unsigned nameBufferLen, const char *hint) const { + for (auto const &iface : ifaces) { + int ret = iface->GetConstantName(value, nameOut, nameBufferLen, hint); + if (ret != 0) return ret; + } + return 0; +} + +const IFaceFunction *IFaceTableMixer::GetFunctionByMessage(int message) const { + for (auto const &iface : ifaces) { + const IFaceFunction *ret = iface->GetFunctionByMessage(message); + if (ret != nullptr) return ret; + } + return nullptr; +} + +IFaceFunction IFaceTableMixer::GetPropertyFuncByMessage(int message) const { + for (auto const &iface : ifaces) { + IFaceFunction ret = iface->GetPropertyFuncByMessage(message); + if (ret.value != -1) return ret; + } + return{ "invalid", -1, iface_void, { iface_void, iface_void } }; +} diff --git a/src/NotepadNext/IFaceTableMixer.h b/src/NotepadNext/IFaceTableMixer.h new file mode 100644 index 000000000..bf612cb89 --- /dev/null +++ b/src/NotepadNext/IFaceTableMixer.h @@ -0,0 +1,44 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef IFACETABLEMIXER_H +#define IFACETABLEMIXER_H + +#include "IFaceTable.h" +#include + +class IFaceTableMixer : public IFaceTableInterface { +private: + std::vector ifaces; + +public: + void AddIFaceTable(IFaceTableInterface *iface) { ifaces.push_back(iface); } + + // IFaceTableInterface + const IFaceConstant *FindConstant(const char *name) const; + const IFaceFunction *FindFunction(const char *name) const; + const IFaceFunction *FindFunctionByConstantName(const char *name) const; + const IFaceFunction *FindFunctionByValue(int value) const; + const IFaceProperty *FindProperty(const char *name) const; + int GetConstantName(int value, char *nameOut, unsigned nameBufferLen, const char *hint) const; + const IFaceFunction *GetFunctionByMessage(int message) const; + IFaceFunction GetPropertyFuncByMessage(int message) const; +}; + +#endif diff --git a/src/NotepadNext/ISearchResultsHandler.h b/src/NotepadNext/ISearchResultsHandler.h new file mode 100644 index 000000000..453d4e2c4 --- /dev/null +++ b/src/NotepadNext/ISearchResultsHandler.h @@ -0,0 +1,32 @@ +/* + * This file is part of Notepad Next. + * Copyright 2023 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + +#include "ScintillaNext.h" + +#include + +class ISearchResultsHandler { +public: + virtual void newSearch(const QString searchTerm) = 0; + virtual void newFileEntry(ScintillaNext *editor) = 0; + virtual void newResultsEntry(const QString line, int lineNumber, int startPositionFromBeginning, int endPositionFromBeginning, int hitCount=1) = 0; + virtual void completeSearch() = 0; +}; diff --git a/src/NotepadNext/LanguageStylesModel.cpp b/src/NotepadNext/LanguageStylesModel.cpp new file mode 100644 index 000000000..a10efd2fc --- /dev/null +++ b/src/NotepadNext/LanguageStylesModel.cpp @@ -0,0 +1,269 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "LanguageStylesModel.h" +#include "ScintillaNext.h" +#include "ComboBoxDelegate.h" + +static inline QRgb convert_color(QRgb c) { + const int red = qRed(c); + const int green = qGreen(c); + const int blue = qBlue(c); + + return qRgb(blue, green, red); +} + +QList caseItems{ + {"SC_CASE_MIXED", SC_CASE_MIXED}, + {"SC_CASE_UPPER", SC_CASE_UPPER}, + {"SC_CASE_LOWER", SC_CASE_LOWER}, + {"SC_CASE_CAMEL", SC_CASE_CAMEL} +}; + +QString val_to_case_str(int val) { + for (const ComboBoxItem &item : caseItems) { + if (item.second == val) { + return item.first; + } + } + + return QString(); +} + +QStringList columns{ + "ID", + "Name", + "Tags", + "Description", + "Font", + "Size", + "Fractional", + "Bold", + "Weight", + "Italic", + "Underline", + "Fore", + "Back", + "EOL Filled", + "Character Set", + "Case", + "Visible", + "Changeable", + "Hotspot", +}; + +LanguageStylesModel::LanguageStylesModel(ScintillaNext *editor, QObject *parent) + : QAbstractTableModel(parent), editor(editor) +{ +} + +QVariant LanguageStylesModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::DisplayRole) { + if (orientation == Qt::Horizontal) { + return columns[section]; + } + } + + return QVariant(); +} + +int LanguageStylesModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return editor->namedStyles(); +} + +int LanguageStylesModel::columnCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return columns.size(); +} + +QVariant LanguageStylesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == Qt::DisplayRole || role == Qt::ToolTipRole || role == Qt::EditRole) { + switch (index.column()) { + case 0: // ID + return QString::number(index.row()); + case 1: // Name + return editor->nameOfStyle(index.row()); + case 2: // Tags + return editor->tagsOfStyle(index.row()); + case 3: // Description + return editor->descriptionOfStyle(index.row()); + case 4: // Font + return editor->styleFont(index.row()); + case 5: // Size + return (int)editor->styleSize(index.row()); + case 6: // Fractional + return (int)editor->styleSizeFractional(index.row()); + case 7: // Bold + if (role == Qt::EditRole) return editor->styleBold(index.row()); + else return editor->styleBold(index.row()) ? "True" : "False"; + case 8: // Weight + return (int)editor->styleWeight(index.row()); + case 9: // Italic + if (role == Qt::EditRole) return editor->styleItalic(index.row()); + else return editor->styleItalic(index.row()) ? "True" : "False"; + case 10: // Underline + if (role == Qt::EditRole) return editor->styleUnderline(index.row()); + else return editor->styleUnderline(index.row()) ? "True" : "False"; + case 11: // Fore + return QColor(convert_color(editor->styleFore(index.row()))); + case 12: // Back + return QColor(convert_color(editor->styleBack(index.row()))); + case 13: // EOL Filled + if (role == Qt::EditRole) return editor->styleEOLFilled(index.row()); + else return editor->styleEOLFilled(index.row()) ? "True" : "False"; + case 14: // Character Set + return (int)editor->styleCharacterSet(index.row()); + case 15: // Case + if (role == Qt::EditRole) return (int)editor->styleCase(index.row()); + else return val_to_case_str(editor->styleCase(index.row())); + case 16: // Visible + if (role == Qt::EditRole) return editor->styleVisible(index.row()); + else return editor->styleVisible(index.row()) ? "True" : "False"; + case 17: // Changeable + if (role == Qt::EditRole) return editor->styleChangeable(index.row()); + else return editor->styleChangeable(index.row()) ? "True" : "False"; + case 18: // Hotspot + if (role == Qt::EditRole) return editor->styleHotSpot(index.row()); + else return editor->styleHotSpot(index.row()) ? "True" : "False"; + default: + break; + } + } + else if (role == Qt::TextAlignmentRole) { + switch (index.column()) { + case 0: + case 5: + case 6: + case 8: + return Qt::AlignCenter; + } + } + else if (role == Qt::DecorationRole) { + if (index.column() == 11) { + return QColor(convert_color(editor->styleFore(index.row()))); + } + else if (index.column() == 12) { + return QColor(convert_color(editor->styleBack(index.row()))); + } + } + + return QVariant(); +} + +bool LanguageStylesModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; + + if (role == Qt::EditRole) { + switch (index.column()) { + case 4: // Font + editor->styleSetFont(index.row(), value.toString().toLatin1().constData()); + break; + case 5: // Size + editor->styleSetSize(index.row(), value.toInt()); + break; + case 6: // Fractional + editor->styleSetSizeFractional(index.row(), value.toInt()); + break; + case 7: // Bold + editor->styleSetBold(index.row(), value.toBool()); + break; + case 8: // Weight + editor->styleSetWeight(index.row(), value.toInt()); + break; + case 9: // Italic + editor->styleSetItalic(index.row(), value.toBool()); + break; + case 10: // Underline + editor->styleSetUnderline(index.row(), value.toBool()); + break; + case 11: // Fore + editor->styleSetFore(index.row(), convert_color(value.value().rgb())); + break; + case 12: // Back + editor->styleSetBack(index.row(), convert_color(value.value().rgb())); + break; + case 13: // EOL Filled + editor->styleSetEOLFilled(index.row(), value.toBool()); + break; + case 15: // Case + editor->styleSetCase(index.row(), value.toInt()); + break; + case 16: // Visible + editor->styleSetVisible(index.row(), value.toBool()); + break; + case 17: // Changeable + editor->styleSetChangeable(index.row(), value.toBool()); + break; + case 18: // Hotspot + editor->styleSetHotSpot(index.row(), value.toBool()); + break; + default: + return false; + } + + editor->colourise(0, -1); + + emit dataChanged(index, index, QVector() << role); + + return true; + } + + return false; +} + +Qt::ItemFlags LanguageStylesModel::flags(const QModelIndex &index) const +{ + const Qt::ItemFlags default_flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + + if (!index.isValid()) + return Qt::NoItemFlags; + + switch (index.column()) { + case 4: // Font + case 5: // Size + case 6: // Fractional + case 7: // Bold + case 8: // Weight + case 9: // Italic + case 10: // Underline + case 11: // Fore + case 12: // Back + case 13: // EOL Filled + case 15: // Case + case 16: // Visible + case 17: // Changeable + case 18: // Hotspot + return default_flags | Qt::ItemIsEditable; + } + + return default_flags; +} diff --git a/src/NotepadNext/LanguageStylesModel.h b/src/NotepadNext/LanguageStylesModel.h new file mode 100644 index 000000000..3e7e724d4 --- /dev/null +++ b/src/NotepadNext/LanguageStylesModel.h @@ -0,0 +1,47 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef LANGUAGESTYLESMODEL_H +#define LANGUAGESTYLESMODEL_H + +#include + +class ScintillaNext; + +class LanguageStylesModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit LanguageStylesModel(ScintillaNext *editor, QObject *parent = nullptr); + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + +private: + ScintillaNext *editor; +}; + +#endif // LANGUAGESTYLESMODEL_H diff --git a/src/NotepadNext/LuaExtension.cpp b/src/NotepadNext/LuaExtension.cpp new file mode 100644 index 000000000..dfd4a66d0 --- /dev/null +++ b/src/NotepadNext/LuaExtension.cpp @@ -0,0 +1,855 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Scintilla.h" +#include "LuaExtension.h" + +#include "IFaceTableMixer.h" +#include "SciIFaceTable.h" + +#include "lua.hpp" + +IFaceTableMixer ifacemixer; + +// From lua.c +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) + +static bool call_function(lua_State *L, int nargs, bool ignoreFunctionReturnValue); + +// Helper function from SciTE +[[maybe_unused]] static int Substitute(std::string &s, const std::string &sFind, const std::string &sReplace) { + int c = 0; + size_t lenFind = sFind.size(); + size_t lenReplace = sReplace.size(); + size_t posFound = s.find(sFind); + while (posFound != std::string::npos) { + s.replace(posFound, lenFind, sReplace); + posFound = s.find(sFind, posFound + lenReplace); + c++; + } + return c; +} + +// Helper function from SciTE +[[maybe_unused]] static bool Exists(const char *fileName) { + bool ret = false; + if (fileName && fileName[0]) { + FILE *fp = fopen(fileName, "rb"); + if (fp) { + ret = true; + fclose(fp); + } + } + return ret; +} + + +// A note on naming conventions: +// I've gone back and forth on this a bit, trying different styles. +// It isn't easy to get something that feels consistent, considering +// that the Lua API uses lower case, underscore-separated words and +// Scintilla of course uses mixed case with no underscores. + +// What I've settled on is that functions that require you to think +// about the Lua stack are likely to be mixed with Lua API functions, +// so these should using a naming convention similar to Lua itself. +// Functions that don't manipulate Lua at a low level should follow +// the normal SciTE convention. There is some grey area of course, +// and for these I just make a judgement call + +static ScintillaEdit *editor; +static lua_State *luaState = 0; +static bool luaDisabled = false; +static bool tracebackEnabled = true; + +typedef int NppExtensionAPIPane; +void hostTrace(const char *s) +{ + qInfo("%s", s); +} +void hostTraceError(const char *s) +{ + qWarning("%s", s); +} + +// Forward declarations +static NppExtensionAPIPane check_pane_object(lua_State *L, int index); +static void push_pane_object(lua_State *L, NppExtensionAPIPane p); +static int iface_function_helper(lua_State *L, const IFaceFunction &func); + +inline void raise_error(lua_State *L, const char *errMsg=NULL) { + luaL_where(L, 1); + if (errMsg) { + lua_pushstring(L, errMsg); + } else { + lua_insert(L, -2); + } + lua_concat(L, 2); + lua_error(L); +} + +inline void raise_ferror(lua_State *L, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + lua_pushvfstring(L, fmt, args); + va_end(args); + raise_error(L); +} + +inline int absolute_index(lua_State *L, int index) { + return ((index < 0) && (index != LUA_REGISTRYINDEX)) ? (lua_gettop(L) + index + 1) : index; +} + +[[maybe_unused]] static int cf_npp_send(lua_State *L) { + // This is reinstated as a replacement for the old :send, which was removed + // due to safety concerns. Is now exposed as npp.SendEditor / npp.SendOutput. + // It is rewritten to be typesafe, checking the arguments against the metadata in + // IFaceTable in the same way that the object interface does. + + IFaceFunction propfunc; + int paneIndex = lua_upvalueindex(1); + check_pane_object(L, paneIndex); + int message = (int)luaL_checkinteger(L, 1); + + lua_pushvalue(L, paneIndex); + lua_replace(L, 1); + + const IFaceFunction *func; + func = SciIFaceTable.GetFunctionByMessage(message); + + if (func == nullptr) { + propfunc = SciIFaceTable.GetPropertyFuncByMessage(message); + if (propfunc.value != -1) func = &propfunc; + } + + if (func != nullptr) { + if (IFaceFunctionIsScriptable(*func)) { + return iface_function_helper(L, *func); + } else { + raise_error(L, "Cannot call send for this function: not scriptable."); + return 0; + } + } else { + raise_error(L, "Message number does not match any published Scintilla / Notepad++ function or property"); + return 0; + } +} + +[[maybe_unused]] static int cf_npp_constname(lua_State *L) { + char constName[100] = ""; + const char *hint = nullptr; + int message = (int)luaL_checkinteger(L, 1); + + hint = luaL_optstring(L, 2, nullptr); + + if (ifacemixer.GetConstantName(message, constName, 100, hint) > 0) { + lua_pushstring(L, constName); + return 1; + } else { + raise_error(L, "Argument does not match any Scintilla / Notepad++ constant"); + return 0; + } +} + +void stackdump(lua_State* l) +{ + int i; + int top = lua_gettop(l); + + for (i = 1; i <= top; i++) + { /* repeat for each level */ + int t = lua_type(l, i); + hostTrace(lua_typename(l, t)); + hostTrace(" "); /* put a separator */ + } + hostTrace("\n"); /* end the listing */ +} + +static NppExtensionAPIPane check_pane_object(lua_State *L, int index) { + NppExtensionAPIPane *pPane = static_cast(luaL_testudata(L, index, "Nn_MT_Pane")); + + if ((!pPane) && lua_istable(L, index)) { + // so that nested objects have a convenient way to do a back reference + int absIndex = absolute_index(L, index); + lua_pushliteral(L, "pane"); + lua_gettable(L, absIndex); + pPane = static_cast(luaL_testudata(L, -1, "Nn_MT_Pane")); + } + + if (pPane) { + return *pPane; + } + + pPane = static_cast(luaL_testudata(L, index, "Nn_MT_Application")); + + // NOTE: I'm not sure what the above comment about the "back reference" means. This may or + // may not apply in this case. So that if statement may need pasted/modified in this case + + if (pPane) { + return *pPane; + } + + if (index == 1) + lua_pushliteral(L, "Self object is missing in pane method or property access."); + else if (index == lua_upvalueindex(1)) + lua_pushliteral(L, "Internal error: pane object expected in closure."); + else + lua_pushliteral(L, "Pane object expected."); + + raise_error(L); + return 0; // this line never reached +} + +static int cf_global_print(lua_State *L) { + int nargs = lua_gettop(L); + + lua_getglobal(L, "tostring"); + + for (int i = 1; i <= nargs; ++i) { + if (i > 1) + hostTrace("\t"); + + const char *argStr = lua_tostring(L, i); + if (argStr) { + hostTrace(argStr); + } else { + lua_pushvalue(L, -1); // tostring + lua_pushvalue(L, i); + lua_call(L, 1, 1); + argStr = lua_tostring(L, -1); + if (argStr) { + hostTrace(argStr); + } else { + raise_error(L, "tostring (called from print) returned a non-string"); + } + lua_settop(L, nargs + 1); + } + } + + hostTrace("\n"); + return 0; +} + +[[maybe_unused]] static bool call_function(lua_State *L, int nargs, bool ignoreFunctionReturnValue=false) { + bool handled = false; + if (L) { + int traceback = 0; + if (tracebackEnabled) { + lua_getglobal(L, "debug"); + lua_getfield(L, -1, "traceback"); + lua_remove(L, -2); + if (lua_isfunction(L, -1)) { + traceback = lua_gettop(L) - nargs - 1; + lua_insert(L, traceback); + } else { + lua_pop(L, 1); + } + } + + int result = lua_pcall(L, nargs, ignoreFunctionReturnValue ? 0 : 1, traceback); + + if (traceback) { + lua_remove(L, traceback); + } + + if (result == LUA_OK) { + if (ignoreFunctionReturnValue) { + handled = true; + } else { + handled = (0 != lua_toboolean(L, -1)); + lua_pop(L, 1); + } + } else if (result == LUA_ERRRUN) { + lua_getglobal(L, "print"); + lua_insert(L, -2); // use pushed error message + lua_pcall(L, 1, 0, 0); + } else { + lua_pop(L, 1); + if (result == LUA_ERRMEM) { + hostTraceError("Memory allocation error\n"); + } else if (result == LUA_ERRERR) { + hostTraceError("An error occurred, but cannot be reported due to failure in _TRACEBACK\n"); + } else { + hostTraceError("Unexpected error\n"); + } + } + } + return handled; +} + +struct ScintillaFailure { + sptr_t status; + explicit ScintillaFailure(sptr_t status_) : status(status_) { + } +}; + +static int iface_function_helper(lua_State *L, const IFaceFunction &func) { + NppExtensionAPIPane p = check_pane_object(L, 1); + + int arg = 2; + + sptr_t params[2] = {0,0}; + + char *stringResult = 0; + enum stringResultType { none, string, tstring } needStringResult = none; + int loopParamCount = 2; + + if (func.paramType[0] == iface_length && func.paramType[1] == iface_string) { + params[0] = static_cast(lua_rawlen(L, arg)); + params[1] = reinterpret_cast(params[0] ? lua_tostring(L, arg) : ""); + loopParamCount = 0; + } else if ((func.paramType[1] == iface_stringresult) || (func.returnType == iface_stringresult)) { + needStringResult = (func.paramType[1] == iface_stringresult) || (func.returnType == iface_stringresult) ? string : tstring; + // The buffer will be allocated later, so it won't leak if Lua does + // a longjmp in response to a bad arg. + if (func.paramType[0] == iface_length) { + loopParamCount = 0; + } else { + loopParamCount = 1; + } + } + + // Specifically handle these 2 messages because they carry the setter in the 2nd param + if (func.value == SCI_SETMARGINLEFT || func.value == SCI_SETMARGINRIGHT) { + params[1] = static_cast(luaL_checkinteger(L, arg++)); + } + else { + for (int i = 0; i < loopParamCount; ++i) { + if (func.paramType[i] == iface_string) { + const char *s = lua_tostring(L, arg++); + params[i] = reinterpret_cast(s ? s : ""); + } else if (func.paramType[i] == iface_keymod) { + int keycode = static_cast(luaL_checkinteger(L, arg++)) & 0xFFFF; + int modifiers = static_cast(luaL_checkinteger(L, arg++)) & (SCMOD_SHIFT|SCMOD_CTRL|SCMOD_ALT); + params[i] = keycode | (modifiers<<16); + } else if (func.paramType[i] == iface_bool) { + params[i] = lua_toboolean(L, arg++); + } else if (IFaceTypeIsNumeric(func.paramType[i])) { + params[i] = static_cast(luaL_checkinteger(L, arg++)); + } + } + } + + if (needStringResult != none) { + sptr_t stringResultLen; + if (needStringResult == string) { + stringResultLen = editor->send(func.value, params[0], 0); + if (stringResultLen > 0) { + // not all string result methods are guaranteed to add a null terminator + stringResult = new char[stringResultLen+1]; + stringResult[stringResultLen]='\0'; + params[1] = reinterpret_cast(stringResult); + } else { + // Is this an error? Are there any cases where it's not an error, + // and where the right thing to do is just return a blank string? + return 0; + } + } + + if (func.paramType[0] == iface_length) { + params[0] = stringResultLen; + } + } + + // Now figure out what to do with the param types and return type. + // - stringresult gets inserted at the start of return tuple. + // - numeric return type gets returned to lua as a number (following the stringresult) + // - other return types e.g. void get dropped. + + sptr_t result = 0; + try { + result = editor->send(func.value, params[0], params[1]); + } + catch (ScintillaFailure &sf) { + std::string failureExplanation; + failureExplanation += "Lua: Scintilla failure "; + failureExplanation += std::to_string(sf.status); + failureExplanation += " for message "; + failureExplanation += std::to_string(func.value); + failureExplanation += ".\n"; + // Reset status before continuing + editor->send(SCI_SETSTATUS, SC_STATUS_OK, 0); + hostTraceError(failureExplanation.c_str()); + } + + int resultCount = 0; + + if (stringResult) { + lua_pushstring(L, stringResult); + delete[] stringResult; + resultCount++; + } + + if (func.returnType == iface_bool) { + lua_pushboolean(L, static_cast(result)); + resultCount++; + } else if (IFaceTypeIsNumeric(func.returnType)) { + lua_pushinteger(L, static_cast(result)); + resultCount++; + } + + return resultCount; +} + +struct IFacePropertyBinding { + NppExtensionAPIPane pane; + const IFaceProperty *prop; +}; + +static int cf_ifaceprop_metatable_index(lua_State *L) { + // if there is a getter, __index calls it + // otherwise, __index raises "property 'name' is write-only". + IFacePropertyBinding *ipb = static_cast(luaL_testudata(L, 1, "Nn_MT_IFacePropertyBinding")); + if (!(ipb && IFacePropertyIsScriptable(*(ipb->prop)))) { + raise_error(L, "Internal error: property binding is improperly set up"); + return 0; + } + if (ipb->prop->getter == 0) { + raise_error(L, "Attempt to read a write-only indexed property"); + return 0; + } + IFaceFunction func = ipb->prop->GetterFunction(); + + // rewrite the stack to match what the function expects. put pane at index 1; param is already at index 2. + push_pane_object(L, ipb->pane); + lua_replace(L, 1); + lua_settop(L, 2); + return iface_function_helper(L, func); +} + +static int cf_ifaceprop_metatable_newindex(lua_State *L) { + IFacePropertyBinding *ipb = static_cast(luaL_testudata(L, 1, "Nn_MT_IFacePropertyBinding")); + if (!(ipb && IFacePropertyIsScriptable(*(ipb->prop)))) { + raise_error(L, "Internal error: property binding is improperly set up"); + return 0; + } + if (ipb->prop->setter == 0) { + raise_error(L, "Attempt to write a read-only indexed property"); + return 0; + } + IFaceFunction func = ipb->prop->SetterFunction(); + + // rewrite the stack to match what the function expects. + // pane at index 1; param at index 2, value at index 3 + push_pane_object(L, ipb->pane); + lua_replace(L, 1); + lua_settop(L, 3); + return iface_function_helper(L, func); +} + +static int cf_pane_iface_function(lua_State *L) { + int funcidx = lua_upvalueindex(1); + const IFaceFunction *func = static_cast(lua_touserdata(L, funcidx)); + if (func) { + return iface_function_helper(L, *func); + } else { + raise_error(L, "Internal error - bad upvalue in iface function closure"); + return 0; + } +} + +static int push_iface_function(lua_State *L, const char *name, IFaceTableInterface *iface) { + auto func = iface->FindFunction(name); + if (func != nullptr) { + if (IFaceFunctionIsScriptable(*func)) { + lua_pushlightuserdata(L, (void*)func); + lua_pushcclosure(L, cf_pane_iface_function, 1); + + // Since Lua experts say it is inefficient to create closures / cfunctions + // in an inner loop, I tried caching the closures in the metatable, and looking + // for them there first. However, it made very little difference and did not + // seem worth the added complexity. - WBD + + return 1; + } + } + return -1; // signal to try next pane index handler +} + +static int push_iface_propval(lua_State *L, const char *name, IFaceTableInterface *iface) { + // this function doesn't raise errors, but returns 0 if the function is not handled. + + auto prop = iface->FindProperty(name); + if (prop != nullptr) { + if (!IFacePropertyIsScriptable(*prop)) { + raise_error(L, "Error: iface property is not scriptable."); + return -1; + } + + if (prop->paramType == iface_void) { + if (prop->getter) { + lua_settop(L, 1); + return iface_function_helper(L, prop->GetterFunction()); + } + } else if (prop->paramType == iface_bool) { + // The bool getter is untested since there are none in the iface. + // However, the following is suggested as a reference protocol. + NppExtensionAPIPane p = check_pane_object(L, 1); + + if (prop->getter) { + if (editor->send(prop->getter, 1, 0)) { + lua_pushnil(L); + return 1; + } else { + lua_settop(L, 1); + lua_pushboolean(L, 0); + return iface_function_helper(L, prop->GetterFunction()); + } + } + } else { + // Indexed property. These return an object with the following behavior: + // if there is a getter, __index calls it + // otherwise, __index raises "property 'name' is write-only". + // if there is a setter, __newindex calls it + // otherwise, __newindex raises "property 'name' is read-only" + + IFacePropertyBinding *ipb = static_cast(lua_newuserdata(L, sizeof(IFacePropertyBinding))); + if (ipb) { + ipb->pane = check_pane_object(L, 1); + ipb->prop = prop; + if (luaL_newmetatable(L, "Nn_MT_IFacePropertyBinding")) { + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cf_ifaceprop_metatable_index); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cf_ifaceprop_metatable_newindex); + lua_settable(L, -3); + } + lua_setmetatable(L, -2); + return 1; + } else { + raise_error(L, "Internal error: failed to allocate userdata for indexed property"); + return -1; + } + } + } + + return -1; // signal to try next pane index handler +} + +static int cf_pane_metatable_index(lua_State *L) { + IFaceTableInterface *iface = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (lua_isstring(L, 2)) { + const char *name = lua_tostring(L, 2); + + // these return the number of values pushed (possibly 0), or -1 if no match + int results = push_iface_function(L, name, iface); + if (results < 0) + results = push_iface_propval(L, name, iface); + + if (results >= 0) { + return results; + } else if (name[0] != '_') { + lua_getmetatable(L, 1); + if (lua_istable(L, -1)) { + lua_pushvalue(L, 2); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) + return 1; + } + } + } + + raise_error(L, "Pane function / readable property / indexed writable property name expected"); + return 0; +} + +static int cf_pane_metatable_newindex(lua_State *L) { + IFaceTableInterface *iface = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (lua_isstring(L, 2)) { + auto prop = iface->FindProperty(lua_tostring(L, 2)); + if (prop != nullptr) { + if (IFacePropertyIsScriptable(*prop)) { + if (prop->setter) { + // stack needs to be rearranged to look like an iface function call + lua_remove(L, 2); + if (prop->paramType == iface_void) { + return iface_function_helper(L, prop->SetterFunction()); + } else if ((prop->paramType == iface_bool)) { + if (!lua_isnil(L, 3)) { + lua_pushboolean(L, 1); + lua_insert(L, 2); + } else { + // the nil will do as a false value. + // just push an arbitrary numeric value that Scintilla will ignore + lua_pushinteger(L, 0); + } + return iface_function_helper(L, prop->SetterFunction()); + + } else { + raise_error(L, "Error - (pane object) cannot assign directly to indexed property"); + } + } else { + raise_error(L, "Error - (pane object) cannot assign to a read-only property"); + } + } + } + } + + raise_error(L, "Error - (pane object) expected the name of a writable property"); + return 0; +} + +void push_pane_object(lua_State *L, NppExtensionAPIPane p) { + *static_cast(lua_newuserdata(L, sizeof(p))) = p; + if (luaL_newmetatable(L, "Nn_MT_Pane")) { + lua_pushlightuserdata(L, &SciIFaceTable); + lua_pushcclosure(L, cf_pane_metatable_index, 1); + lua_setfield(L, -2, "__index"); + lua_pushlightuserdata(L, &SciIFaceTable); + lua_pushcclosure(L, cf_pane_metatable_newindex, 1); + lua_setfield(L, -2, "__newindex"); + + // Push built-in functions into the metatable, where the custom + // __index metamethod will find them. + } + lua_setmetatable(L, -2); +} + +static int cf_global_metatable_index(lua_State *L) { + if (lua_isstring(L, 2)) { + const char *name = lua_tostring(L, 2); + if ((name[0] < 'A') || (name[0] > 'Z') || ((name[1] >= 'a') && (name[1] <= 'z'))) { + // short circuit; iface constants are always upper-case and start with a letter + return 0; + } + + auto con = ifacemixer.FindConstant(name); + if (con != nullptr) { + lua_pushinteger(L, con->value); + return 1; + } else { + auto func = ifacemixer.FindFunctionByConstantName(name); + if (func != nullptr) { + lua_pushinteger(L, func->value); + + // FindFunctionByConstantName is slow, so cache the result into the + // global table. My tests show this gives an order of magnitude + // improvement. + lua_pushvalue(L, 2); + lua_pushvalue(L, -2); + lua_rawset(L, 1); + + return 1; + } + } + } + + return 0; // global namespace access should not raise errors +} + +static int LuaPanicFunction(lua_State *L) { + if (L == luaState) { + lua_close(luaState); + luaState = NULL; + luaDisabled = true; + } + hostTraceError("\nError occurred in unprotected call. This is very bad.\n"); + return 1; +} + +static bool InitGlobalScope() { + tracebackEnabled = true; + + if (!luaDisabled) { + if (!luaState) { + luaDisabled = true; + hostTraceError("Scripting engine failed to initialise\n"); + return false; + } + lua_atpanic(luaState, LuaPanicFunction); + + } + else { + return false; + } + + ifacemixer.AddIFaceTable(&SciIFaceTable); + + // ...register standard libraries + luaL_openlibs(luaState); + + // override a library function whose default impl uses stdout + lua_register(luaState, "print", cf_global_print); + + // pane objects + push_pane_object(luaState, 0); + lua_setglobal(luaState, "editor"); + + // get global environment table from registry + lua_pushglobaltable(luaState); + // Metatable for global namespace, to publish iface constants + if (luaL_newmetatable(luaState, "Nn_MT_GlobalScope")) { + lua_pushcfunction(luaState, cf_global_metatable_index); + lua_setfield(luaState, -2, "__index"); + } + // set global index callback hook + lua_setmetatable(luaState, -2); + // remove the global environment table from the stack + lua_pop(luaState, 1); + + return true; +} + + +LuaExtension::LuaExtension() {} +LuaExtension::~LuaExtension() {} + +LuaExtension &LuaExtension::Instance() { + static LuaExtension singleton; + return singleton; +} + +bool LuaExtension::Initialise(lua_State *L, ScintillaNext *editor_) { + luaState = L; + editor = editor_; + InitGlobalScope(); + + return false; +} + +void LuaExtension::setEditor(ScintillaEdit *editor_) { + editor = editor_; +} + +bool LuaExtension::Finalise() { + if (luaState) { + lua_close(luaState); + } + + luaState = NULL; + editor = NULL; + + return false; +} + +bool LuaExtension::RunString(const char *s) { + if (luaState || InitGlobalScope()) { + int status = luaL_loadbuffer(luaState, s, strlen(s), "=File"); + + if (status == LUA_OK) { + status = lua_pcall(luaState, 0, LUA_MULTRET, 0); + } + + if (status != LUA_OK) { + // Print an error message + hostTraceError(lua_tostring(luaState, -1)); + hostTraceError("\n"); + lua_settop(luaState, 0); /* clear stack */ + return false; + } + + lua_settop(luaState, 0); /* clear stack */ + } + + return true; +} + +bool LuaExtension::OnExecute(const char *s) { + static bool isFirstLine = true; + static std::string chunk; + int status = 0; + + if (luaState || InitGlobalScope()) { + if (isFirstLine) { + // First try to compile the chunk as a return statement + const char *retline = lua_pushfstring(luaState, "return %s;", s); + status = luaL_loadbuffer(luaState, retline, strlen(retline), "=Console"); + if (status == 0) lua_remove(luaState, -2); + else lua_pop(luaState, 2); + + if (status == LUA_OK) { + // It worked, let's call it + status = lua_pcall(luaState, 0, LUA_MULTRET, 0); + } + else { + // Else let's just try it as is + status = luaL_loadbuffer(luaState, s, strlen(s), "=Console"); + if (status == LUA_OK) { + status = lua_pcall(luaState, 0, LUA_MULTRET, 0); + } + else if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(luaState, -1, &lmsg); + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { + lua_pop(luaState, 1); + isFirstLine = false; + chunk = s; + return false; + } + } + } + } + else { + // Append the new line to what we've gotten so far + chunk.append("\n"); + chunk.append(s); + status = luaL_loadbuffer(luaState, chunk.c_str(), chunk.length(), "=Console"); + if (status == LUA_OK) { + status = lua_pcall(luaState, 0, LUA_MULTRET, 0); + } + else if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(luaState, -1, &lmsg); + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { + lua_pop(luaState, 1); + return false; + } + } + } + + // At this point *something* ran so clear out some data + chunk.clear(); + isFirstLine = true; + + if (status == LUA_OK) { + if (lua_gettop(luaState) > 0) { /* any result to print? */ + lua_getglobal(luaState, "print"); + lua_insert(luaState, 1); + if (lua_pcall(luaState, lua_gettop(luaState) - 1, 0, 0) != 0) + hostTraceError("error calling " LUA_QL("print")); + } + // else everything finished fine but had no return value + } + else { + // Print an error message if possible + const char *errmsg = lua_tostring(luaState, -1); + if (errmsg) { + hostTraceError(errmsg); + hostTraceError("\n"); + } + else { + hostTraceError("error\n"); + } + } + lua_settop(luaState, 0); /* clear stack */ + } + return true; +} diff --git a/src/NotepadNext/LuaExtension.h b/src/NotepadNext/LuaExtension.h new file mode 100644 index 000000000..89104430b --- /dev/null +++ b/src/NotepadNext/LuaExtension.h @@ -0,0 +1,105 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef LUAEXTENSION_H +#define LUAEXTENSION_H + +#include "ScintillaNext.h" +#include + +class ScintillaNext; +struct lua_State; + +class LuaExtension final { +private: + LuaExtension(); // Singleton + LuaExtension(const LuaExtension &); // Disable copy ctor + void operator=(const LuaExtension &); // Disable operator= + +public: + static LuaExtension &Instance(); + + ~LuaExtension(); + + bool Initialise(lua_State *L, ScintillaNext *editor_); + void setEditor(ScintillaEdit *editor_); + bool Finalise(); + + // Helper methods + bool RunString(const char *s); + bool OnExecute(const char *s); + void CallShortcut(int id); + + // Scintilla callbacks + //bool OnStyle(unsigned int startPos, int lengthDoc, int initStyle, StyleWriter *styler); + //bool OnChar(const SCNotification *sc); + //bool OnSavePointReached(const SCNotification *sc); + //bool OnSavePointLeft(const SCNotification *sc); + //bool OnModifyAttemptRO(const SCNotification *sc); + //bool OnDoubleClick(const SCNotification *sc); + //bool OnUpdateUI(const SCNotification *sc); + //bool OnModification(const SCNotification *sc); + //bool OnMacroRecord(const SCNotification *sc); + //bool OnMarginClick(const SCNotification *sc); + //bool OnNeedShown(const SCNotification *sc); + //bool OnPainted(const SCNotification *sc); + //bool OnUserListSelection(const SCNotification *sc); + //bool OnDwellStart(const SCNotification *sc); + //bool OnDwellEnd(const SCNotification *sc); + //bool OnZoom(const SCNotification *sc); + //bool OnHotSpotClick(const SCNotification *sc); + //bool OnHotSpotDoubleClick(const SCNotification *sc); + //bool OnHotSpotReleaseClick(const SCNotification *sc); + //bool OnIndicatorClick(const SCNotification *sc); + //bool OnIndicatorRelease(const SCNotification *sc); + //bool OnCallTipClick(const SCNotification *sc); + //bool OnAutoCSelection(const SCNotification *sc); + //bool OnAutoCCancelled(const SCNotification *sc); + //bool OnAutoCCharDeleted(const SCNotification *sc); + //bool OnFocusIn(const SCNotification *sc); + //bool OnFocusOut(const SCNotification *sc); + + //// Notepad++ callbacks + //bool OnReady(); + //bool OnToolBarModification(); + //bool OnBeforeClose(const char *filename, uptr_t bufferid); + //bool OnOpen(const char *filename, uptr_t bufferid); + //bool OnClose(); + //bool OnBeforeOpen(const char *filename, uptr_t bufferid); + //bool OnBeforeSave(const char *filename, uptr_t bufferid); + //bool OnSave(const char *filename, uptr_t bufferid); + //bool OnShutdown(); + //bool OnSwitchFile(const char *filename, uptr_t bufferid); + //bool OnLangChange(); + //bool OnFileBeforeLoad(); + //bool OnFileLoadFailed(); + //bool OnReadOnlyChanged(const char *filename, uptr_t bufferid, int status); + //bool OnDocOrderChanged(const char *filename, uptr_t bufferid, int newIndex); + //bool OnSnapshotDirtyFileLoaded(const char *filename, uptr_t bufferid); + //bool OnBeforeShutdown(); + //bool OnCancelShutdown(); + //bool OnFileBeforeRename(const char *filename, uptr_t bufferid); + //bool OnFileRenameCancel(const char *filename, uptr_t bufferid); + //bool OnFileRenamed(const char *filename, uptr_t bufferid); + //bool OnFileBeforeDelete(const char *filename, uptr_t bufferid); + //bool OnFileDeleteFailed(const char *filename, uptr_t bufferid); + //bool OnFileDeleted(); +}; + +#endif diff --git a/src/NotepadNext/LuaState.cpp b/src/NotepadNext/LuaState.cpp new file mode 100644 index 000000000..1b175da13 --- /dev/null +++ b/src/NotepadNext/LuaState.cpp @@ -0,0 +1,182 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "LuaState.h" +#include "lua.hpp" + +#include + +#include +#include + +std::string dumpLuaState(lua_State *L) { + std::stringstream ostr; + int i; + int top = lua_gettop(L); + ostr << "top=" << top << ":\n"; + for (i = 1; i <= top; ++i) { + int t = lua_type(L, i); + switch(t) { + case LUA_TSTRING: + ostr << " " << i << ": '" << lua_tostring(L, i) << "'\n"; + break; + case LUA_TBOOLEAN: + ostr << " " << i << ": " << + (lua_toboolean(L, i) ? "true" : "false") << "\n"; + break; + case LUA_TNUMBER: + ostr << " " << i << ": " << lua_tonumber(L, i) << "\n"; + break; + default: + ostr << " " << i << ": TYPE=" << lua_typename(L, t) << "\n"; + break; + } + } + return ostr.str(); +} + +static int require_resource(lua_State *L) +{ + const char *module = luaL_checkstring(L, 1); + + QString module_file = QString(":/%1/%2.lua").arg(luaLanguagePath, module); + QFile f(module_file); + + lua_pop(L, 1); + + if (f.exists()) { + f.open(QFile::ReadOnly); + luaL_loadstring(L, f.readAll().constData()); + f.close(); + + // At this point either the function or an error string is on the stack + } + else { + lua_pushfstring(L, "\n\tno file '%s'", module_file.toLatin1().constData()); + } + + return 1; +} + +LuaState::LuaState() +{ + qInfo(Q_FUNC_INFO); + + L = luaL_newstate(); + luaL_openlibs(L); + + // Remove the searchers used for finding files on the file system + execute("table.remove(package.searchers, 4); table.remove(package.searchers, 3); table.remove(package.searchers, 2)"); + + for(int i = 0; i < 3; ++i) { + lua_getglobal(L, "table"); + lua_getfield(L, -1, "remove"); + lua_remove(L, -2); + + lua_getglobal(L, "package"); + lua_getfield(L, -1, "searchers"); + lua_remove(L, -2); + lua_call(L, 1, 0); + } + + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + lua_remove(L, -2); + + lua_getglobal(L, "package"); + lua_getfield(L, -1, "searchers"); + lua_remove(L, -2); + + lua_pushcfunction(L, require_resource); + + lua_call(L, 2, 0); +} + +LuaState::~LuaState() +{ + if (L) { + lua_close(L); + L = Q_NULLPTR; + } +} + +void LuaState::execute(const char *statement, bool clear) +{ + // There may be other things on the stack so save the top of it + const int stacktop = lua_gettop(L); + + int status = luaL_loadstring(L, statement); + + if (status == LUA_OK) { + status = lua_pcall(L, 0, LUA_MULTRET, 0); + } + else if (status == LUA_ERRSYNTAX) { + qWarning("LUA_ERRSYNTAX: %s", statement); + } + else if (status == LUA_ERRMEM) { + qFatal("Lua memory allocation error"); + } + + if (status != LUA_OK) { + // Print an error message + //writeErrorToOutput(lua_tostring(L, -1)); + //writeErrorToOutput("\r\n"); + qWarning("%s", lua_tostring(L, -1)); + } + + if (clear) + lua_settop(L, stacktop); +} + +void LuaState::execute(const QString &statement) +{ + execute(statement.toLatin1().constData()); +} + +void LuaState::executeFile(const QString &fileName) +{ + QFile ff(fileName); + + if (!ff.open(QFile::ReadOnly)) { + qFatal("Cannot execute file: %s", fileName.toLatin1().constData()); + } + + execute(ff.readAll().constData()); + + ff.close(); +} + +void LuaState::clearStack() +{ + lua_settop(L, 0); +} + +void LuaState::raiseError(const char *errorMessage) +{ + luaL_where(L, 1); + if (errorMessage) { + lua_pushstring(L, errorMessage); + } else { + lua_insert(L, -2); + } + + lua_concat(L, 2); + lua_error(L); +} + diff --git a/src/NotepadNext/LuaState.h b/src/NotepadNext/LuaState.h new file mode 100644 index 000000000..f22226b3d --- /dev/null +++ b/src/NotepadNext/LuaState.h @@ -0,0 +1,97 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef LUASTATE_H +#define LUASTATE_H + +#include +#include +#include +#include "lua.hpp" + +struct lua_State; + +extern QString luaLanguagePath; + +class LuaState +{ +public: + LuaState(); + ~LuaState(); + + void execute(const char *statement, bool clear = true); + void execute(const QString& statement); + void executeFile(const QString &fileName); + + template + T executeAndReturn(const char *statement); + + void clearStack(); + + void raiseError(const char *errorMessage = Q_NULLPTR); + + lua_State *L = Q_NULLPTR; +private: +}; + +template<> +inline bool LuaState::executeAndReturn(const char *statement) +{ + execute(statement, false); + luaL_checktype(L, 1, LUA_TBOOLEAN); + + bool b = lua_toboolean(L, 1); + lua_pop(L, 1); + + return b; +} + +template<> +inline QString LuaState::executeAndReturn(const char *statement) +{ + execute(statement, false); + luaL_checktype(L, 1, LUA_TSTRING); + + QString s(lua_tostring(L, 1)); + lua_pop(L, 1); + + return s; +} + +template<> +inline QStringList LuaState::executeAndReturn(const char *statement) +{ + execute(statement, false); + luaL_checktype(L, 1, LUA_TTABLE); + + QStringList list; + + /* table is in the stack at index 't' */ + lua_pushnil(L); /* first key */ + while (lua_next(L, 1) != 0) { + list << lua_tostring(L, -1); + lua_pop(L, 1); + } + lua_pop(L, 1); + + return list; +} + + +#endif // LUASTATE_H diff --git a/src/NotepadNext/Macro.cpp b/src/NotepadNext/Macro.cpp new file mode 100644 index 000000000..198260a7d --- /dev/null +++ b/src/NotepadNext/Macro.cpp @@ -0,0 +1,139 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "Macro.h" + +using namespace Scintilla; + +Macro::Macro() : name("") {} + +Macro::~Macro() +{ +} + +void Macro::addMacroStep(Message message, uptr_t wParam, sptr_t lParam) +{ + qInfo(Q_FUNC_INFO); + + // Combine ReplaceSel messages into a single string + if (message == Message::ReplaceSel && !steps.empty() && steps.constLast().message == Message::ReplaceSel) { + steps.last().str.append(reinterpret_cast(lParam)); + } + // Combine DeleteBack (backspace) with ReplaceSel + else if (message == Message::DeleteBack && !steps.empty() && steps.constLast().message == Message::ReplaceSel) { + if (steps.last().str.size() == 1) { + // A single char left so just remove the action + steps.takeLast(); + } + else { + steps.last().str.chop(1); + } + } + else { + steps.append(MacroStep(message, wParam, lParam)); + } + +#ifdef QT_DEBUG + for (const MacroStep &step : steps) { + qInfo("%s", qUtf8Printable(step.toString())); + } +#endif +} + +void Macro::addMacroStep(MacroStep step) +{ + steps.append(step); +} + +void Macro::replay(ScintillaNext *editor, int n) const +{ + qInfo(Q_FUNC_INFO); + + editor->beginUndoAction(); + + while (n > 0) { + for (const MacroStep &step : steps) { + step.replay(editor); + } + + --n; + } + + editor->endUndoAction(); +} + +void Macro::replayTillEndOfFile(ScintillaNext *editor) const +{ + qInfo(Q_FUNC_INFO); + + editor->beginUndoAction(); + + do { + int length = editor->length(); + int curPos = editor->currentPos(); + + replay(editor); + + // The doc can shrink...yay + if (editor->length() < length) { + continue; + } + // The doc can grow... + else if(editor->length() > length) { + // are we going to catch up? + int deltaLength = editor->length() - length; + int deltaPos = editor->currentPos() - curPos; + if (deltaPos > deltaLength) { + // Cursor position is moving forward more than document is growing + continue; + } + } + // the file can stay the same + else { + // is the cursor moving? + if (editor->currentPos() != curPos) { + continue; + } + } + + break; + } while (true); + + editor->endUndoAction(); +} + +QString Macro::getName() const +{ + return name; +} + +void Macro::setName(const QString &value) +{ + name = value; +} + +QDataStream &operator<<(QDataStream& stream, const Macro ¯o) +{ + return stream << macro.name << macro.steps; +} + +QDataStream &operator>>(QDataStream& stream, Macro ¯o) +{ + return stream >> macro.name >> macro.steps; +} diff --git a/src/NotepadNext/Macro.h b/src/NotepadNext/Macro.h new file mode 100644 index 000000000..73b8aa6bb --- /dev/null +++ b/src/NotepadNext/Macro.h @@ -0,0 +1,55 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MACRO_H +#define MACRO_H + +#include "MacroStep.h" + +class Macro +{ +public: + Macro(); + + ~Macro(); + + void addMacroStep(Scintilla::Message message, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); + void addMacroStep(MacroStep step); + + int size() const { return steps.size(); } + + void replay(ScintillaNext *editor, int n = 1) const; + void replayTillEndOfFile(ScintillaNext *editor) const; + + QString getName() const; + void setName(const QString &value); + + QVector &getSteps() { return steps; } + + friend QDataStream &operator<<(QDataStream& stream, const Macro &Macro); + friend QDataStream &operator>>(QDataStream& stream, Macro &Macro); + +private: + QVector steps; + QString name; +}; +Q_DECLARE_METATYPE(Macro) +Q_DECLARE_METATYPE(Macro*) + +#endif // MACRO_H diff --git a/src/NotepadNext/MacroListModel.cpp b/src/NotepadNext/MacroListModel.cpp new file mode 100644 index 000000000..eb1999078 --- /dev/null +++ b/src/NotepadNext/MacroListModel.cpp @@ -0,0 +1,85 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "MacroListModel.h" + +MacroListModel::MacroListModel(QObject *parent, MacroManager *mm) : + QAbstractListModel(parent), + macroManager(mm) +{ +} + +int MacroListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return macroManager->availableMacros().size(); +} + +QVariant MacroListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == Qt::DisplayRole || role == Qt::ToolTipRole) { + return macroManager->availableMacros()[index.row()]->getName(); + } + + return QVariant(); +} + +bool MacroListModel::removeRows(int row, int count, const QModelIndex &parent) +{ + Q_UNUSED(parent); + + beginRemoveRows(QModelIndex(), row, row + count - 1); + + while (count--) { + delete macroManager->availableMacros().takeAt(row); + } + + endRemoveRows(); + + return true; +} + +bool MacroListModel::insertRows(int row, int count, const QModelIndex &parent) +{ + if (count < 1 || row < 0 || row > rowCount(parent)) + return false; + + beginInsertRows(QModelIndex(), row, row + count - 1); + + for (int r = 0; r < count; ++r) { + macroManager->availableMacros().insert(row, new Macro()); + } + + endInsertRows(); + + return true; +} + +Macro *MacroListModel::macro(const QModelIndex &index) +{ + if (index.isValid()) + return macroManager->availableMacros()[index.row()]; + else + return Q_NULLPTR; +} diff --git a/src/NotepadNext/MacroListModel.h b/src/NotepadNext/MacroListModel.h new file mode 100644 index 000000000..3af6f5e85 --- /dev/null +++ b/src/NotepadNext/MacroListModel.h @@ -0,0 +1,48 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MACROLISTMODEL_H +#define MACROLISTMODEL_H + + +#include + +#include "MacroManager.h" + + +class MacroListModel : public QAbstractListModel +{ + Q_OBJECT + +public : + MacroListModel(QObject * parent, MacroManager *mm); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + + bool removeRows(int row, int count, const QModelIndex &parent) override; + bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override; + + Macro *macro(const QModelIndex &index); + +private: + MacroManager *macroManager; +}; + +#endif // MACROLISTMODEL_H diff --git a/src/NotepadNext/MacroManager.cpp b/src/NotepadNext/MacroManager.cpp new file mode 100644 index 000000000..51e063055 --- /dev/null +++ b/src/NotepadNext/MacroManager.cpp @@ -0,0 +1,140 @@ +/* + * This file is part of Notepad Next. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "MacroManager.h" +#include "ApplicationSettings.h" + +MacroManager::MacroManager(QObject *parent) : + QObject{parent} +{ + qInfo(Q_FUNC_INFO); + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + qRegisterMetaTypeStreamOperators("Macro"); +#else + // HACK: For some reason this is required to make QVariant recognize it as a valid type + // see https://stackoverflow.com/q/70974383 + QMetaType::fromType().hasRegisteredDataStreamOperators(); +#endif + + loadSettings(); +} + +MacroManager::~MacroManager() +{ + saveSettings(); +} + +void MacroManager::startRecording(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + Q_ASSERT(_isRecording == false); + + _isRecording = true; + + recorder.startRecording(editor); + + emit recordingStarted(); +} + +void MacroManager::stopRecording() +{ + qInfo(Q_FUNC_INFO); + Q_ASSERT(_isRecording == true); + + _isRecording = false; + + Macro *m = recorder.stopRecording(); + + if (m->size() == 0) { + // If there were no actions recorded, delete it + delete m; + } + else { + if (isCurrentMacroSaved == false) { + // The previous current macro wasn't saved and we are getting ready to point to something else, delete it + delete currentMacro; + } + + isCurrentMacroSaved = false; + currentMacro = m; + } + + emit recordingStopped(); +} + +void MacroManager::loadSettings() +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings settings; + + int size = settings.beginReadArray("Macros"); + for (int i = 0; i < size; ++i) { + settings.setArrayIndex(i); + + if (settings.value("Macro").canConvert()) { + Macro *m = new Macro(settings.value("Macro").value()); + macros.append(m); + } + else { + qWarning("MacroManager: Skipping invalid Macro"); + } + } + settings.endArray(); +} + +void MacroManager::saveSettings() const +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings settings; + + settings.remove("Macros"); + + if (macros.size() > 0) { + settings.beginWriteArray("Macros"); + for (int i = 0; i < macros.size(); ++i) { + settings.setArrayIndex(i); + settings.setValue("Macro", QVariant::fromValue(*macros.at(i))); + } + settings.endArray(); + } +} + +void MacroManager::replayCurrentMacro(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + currentMacro->replay(editor); +} + +void MacroManager::saveCurrentMacro(const QString ¯oName) +{ + qInfo(Q_FUNC_INFO); + + isCurrentMacroSaved = true; + + currentMacro->setName(macroName); + macros.append(currentMacro); +} + +bool MacroManager::hasCurrentUnsavedMacro() const +{ + return currentMacro != Q_NULLPTR && isCurrentMacroSaved == false; +} diff --git a/src/NotepadNext/MacroManager.h b/src/NotepadNext/MacroManager.h new file mode 100644 index 000000000..886f44434 --- /dev/null +++ b/src/NotepadNext/MacroManager.h @@ -0,0 +1,63 @@ +/* + * This file is part of Notepad Next. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef MACROMANAGER_H +#define MACROMANAGER_H + +#include "MacroRecorder.h" + +#include + + +class MacroManager : public QObject +{ + Q_OBJECT + +public: + explicit MacroManager(QObject *parent = nullptr); + virtual ~MacroManager(); + + bool isRecording() const; + QVector &availableMacros() { return macros; }; + + void replayCurrentMacro(ScintillaNext *editor); + void saveCurrentMacro(const QString ¯oName); + bool hasCurrentUnsavedMacro() const; + Macro *getCurrentMacro() const { return currentMacro; } + +public slots: + void startRecording(ScintillaNext *editor); + void stopRecording(); + +private slots: + void loadSettings(); + void saveSettings() const; + +signals: + void recordingStarted(); + void recordingStopped(); + +private: + MacroRecorder recorder; + Macro *currentMacro = Q_NULLPTR; + QVector macros; + bool _isRecording = false; + bool isCurrentMacroSaved = false; +}; + +#endif // MACROMANAGER_H diff --git a/src/NotepadNext/MacroRecorder.cpp b/src/NotepadNext/MacroRecorder.cpp new file mode 100644 index 000000000..9c47ed57d --- /dev/null +++ b/src/NotepadNext/MacroRecorder.cpp @@ -0,0 +1,59 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "MacroRecorder.h" +#include "ScintillaNext.h" +#include + +using namespace Scintilla; + + +MacroRecorder::MacroRecorder(QObject *parent) : + QObject(parent) +{ +} + +void MacroRecorder::startRecording(ScintillaNext *editor) +{ + this->editor = editor; + connect(editor, &ScintillaNext::macroRecord, this, &MacroRecorder::recordMacroStep); + + // We don't "own" the macro so don't delete it if it is a valid pointer + macro = new Macro(); + + editor->startRecord(); +} + +Macro *MacroRecorder::stopRecording() +{ + disconnect(editor, &ScintillaNext::macroRecord, this, &MacroRecorder::recordMacroStep); + + editor->stopRecord(); + + Macro *m = macro; + macro = Q_NULLPTR; + return m; +} + +void MacroRecorder::recordMacroStep(Message message, uptr_t wParam, sptr_t lParam) +{ + qInfo(Q_FUNC_INFO); + + macro->addMacroStep(message, wParam, lParam); +} diff --git a/src/NotepadNext/MacroRecorder.h b/src/NotepadNext/MacroRecorder.h new file mode 100644 index 000000000..b176107d0 --- /dev/null +++ b/src/NotepadNext/MacroRecorder.h @@ -0,0 +1,48 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MACRORECORDER_H +#define MACRORECORDER_H + +#include + +#include "ScintillaNext.h" +#include "Macro.h" + + + +class MacroRecorder : public QObject +{ + Q_OBJECT + +public: + MacroRecorder(QObject *parent = nullptr); + + void startRecording(ScintillaNext *editor); + Macro *stopRecording(); + +public slots: + void recordMacroStep(Scintilla::Message message, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); + +private: + ScintillaNext *editor = Q_NULLPTR; + Macro *macro = Q_NULLPTR; +}; + +#endif // MACRORECORDER_H diff --git a/src/NotepadNext/MacroStep.cpp b/src/NotepadNext/MacroStep.cpp new file mode 100644 index 000000000..a28ae8a18 --- /dev/null +++ b/src/NotepadNext/MacroStep.cpp @@ -0,0 +1,249 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include + +#include "ScintillaNext.h" +#include "MacroStep.h" + + +using namespace Scintilla; + + +QMap messageData { + { Scintilla::Message::Cut, "Cut" }, + { Scintilla::Message::Copy, "Copy" }, + { Scintilla::Message::Paste, "Paste" }, + { Scintilla::Message::Clear, "Clear" }, + { Scintilla::Message::ReplaceSel, "Replace Selection" }, + //{ Scintilla::Message::AddText, "Add Text" }, + //{ Scintilla::Message::InsertText, "Insert Text" }, + //{ Scintilla::Message::AppendText, "Append Text" }, + { Scintilla::Message::ClearAll, "Clear All" }, + { Scintilla::Message::SelectAll, "Select All" }, + //{ Scintilla::Message::GotoLine, "GotoLine" }, + //{ Scintilla::Message::GotoPos, "GotoPos" }, + { Scintilla::Message::SearchAnchor, "Search Anchor" }, + { Scintilla::Message::SearchNext, "Search Next" }, + { Scintilla::Message::SearchPrev, "Search Prev" }, + { Scintilla::Message::LineDown, "Line Down" }, + { Scintilla::Message::LineDownExtend, "Line Down Extend" }, + { Scintilla::Message::ParaDown, "Para Down" }, + { Scintilla::Message::ParaDownExtend, "Para Down Extend" }, + { Scintilla::Message::LineUp, "Line Up" }, + { Scintilla::Message::LineUpExtend, "Line Up Extend" }, + { Scintilla::Message::ParaUp, "Para Up" }, + { Scintilla::Message::ParaUpExtend, "Para Up Extend" }, + { Scintilla::Message::CharLeft, "Char Left" }, + { Scintilla::Message::CharLeftExtend, "Char Left Extend" }, + { Scintilla::Message::CharRight, "Char Right" }, + { Scintilla::Message::CharRightExtend, "Char Right Extend" }, + { Scintilla::Message::WordLeft, "Word Left" }, + { Scintilla::Message::WordLeftExtend, "Word Left Extend" }, + { Scintilla::Message::WordRight, "WordRight" }, + { Scintilla::Message::WordRightExtend, "Word Right Extend" }, + { Scintilla::Message::WordPartLeft, "Word Part Left" }, + { Scintilla::Message::WordPartLeftExtend, "Word Part Left Extend" }, + { Scintilla::Message::WordPartRight, "Word Part Right" }, + { Scintilla::Message::WordPartRightExtend, "Word Part Right Extend" }, + { Scintilla::Message::WordLeftEnd, "Word Left End" }, + { Scintilla::Message::WordLeftEndExtend, "Word Left End Extend" }, + { Scintilla::Message::WordRightEnd, "Word Right End" }, + { Scintilla::Message::WordRightEndExtend, "Word Right End Extend" }, + { Scintilla::Message::Home, "Home" }, + { Scintilla::Message::HomeExtend, "Home Extend" }, + { Scintilla::Message::LineEnd, "Line End" }, + { Scintilla::Message::LineEndExtend, "Line End Extend" }, + { Scintilla::Message::HomeWrap, "Home Wrap" }, + { Scintilla::Message::HomeWrapExtend, "Home Wrap Extend" }, + { Scintilla::Message::LineEndWrap, "Line End Wrap" }, + { Scintilla::Message::LineEndWrapExtend, "Line End Wrap Extend" }, + { Scintilla::Message::DocumentStart, "Document Start" }, + { Scintilla::Message::DocumentStartExtend, "Document Start Extend" }, + { Scintilla::Message::DocumentEnd, "Document End" }, + { Scintilla::Message::DocumentEndExtend, "Document End Extend" }, + //{ Scintilla::Message::StutteredPageUp, "Stuttered Page Up" }, + //{ Scintilla::Message::StutteredPageUpExtend, "Stuttered Page Up Extend" }, + //{ Scintilla::Message::StutteredPageDown, "Stuttered Page Down" }, + //{ Scintilla::Message::StutteredPageDownExtend, "Stuttered Page Down Extend" }, + { Scintilla::Message::PageUp, "Page Up" }, + { Scintilla::Message::PageUpExtend, "Page Up Extend" }, + { Scintilla::Message::PageDown, "Page Down" }, + { Scintilla::Message::PageDownExtend, "Page Down Extend" }, + { Scintilla::Message::EditToggleOvertype, "Edit Toggle Overtype" }, + { Scintilla::Message::Cancel, "Cancel" }, + { Scintilla::Message::DeleteBack, "Delete Back" }, + { Scintilla::Message::Tab, "Tab" }, + { Scintilla::Message::BackTab, "Back Tab" }, + { Scintilla::Message::FormFeed, "Form Feed" }, + { Scintilla::Message::VCHome, "VC Home" }, + { Scintilla::Message::VCHomeExtend, "VC Home Extend" }, + { Scintilla::Message::VCHomeWrap, "VC Home Wrap" }, + { Scintilla::Message::VCHomeWrapExtend, "VC Home Wrap Extend" }, + { Scintilla::Message::VCHomeDisplay, "VCHome Display" }, + { Scintilla::Message::VCHomeDisplayExtend, "VC Home Display Extend" }, + { Scintilla::Message::DelWordLeft, "Delete Word Left" }, + { Scintilla::Message::DelWordRight, "Delete Word Right" }, + { Scintilla::Message::DelWordRightEnd, "Delete Word Right End" }, + { Scintilla::Message::DelLineLeft, "Delete Line Left" }, + { Scintilla::Message::DelLineRight, "Delete Line Right" }, + { Scintilla::Message::LineCopy, "Line Copy" }, + { Scintilla::Message::LineCut, "Line Cut" }, + { Scintilla::Message::LineDelete, "Line Delete" }, + { Scintilla::Message::LineTranspose, "Line Transpose" }, + { Scintilla::Message::LineReverse, "Line Reverse" }, + { Scintilla::Message::LineDuplicate, "Line Duplicate" }, + { Scintilla::Message::LowerCase, "Lower Case" }, + { Scintilla::Message::UpperCase, "Upper Case" }, + { Scintilla::Message::LineScrollDown, "Line Scroll Down" }, + { Scintilla::Message::LineScrollUp, "Line Scroll Up" }, + { Scintilla::Message::DeleteBackNotLine, "Delete Back Not Line" }, + { Scintilla::Message::HomeDisplay, "Home Display" }, + { Scintilla::Message::HomeDisplayExtend, "Home Display Extend" }, + { Scintilla::Message::LineEndDisplay, "Line End Display" }, + { Scintilla::Message::LineEndDisplayExtend, "Line End Display Extend" }, + //{ Scintilla::Message::SetSelectionMode, "Set Selection Mode" }, + { Scintilla::Message::LineDownRectExtend, "Line Down Rect Extend" }, + { Scintilla::Message::LineUpRectExtend, "Line Up Rect Extend" }, + { Scintilla::Message::CharLeftRectExtend, "Char Left Rect Extend" }, + { Scintilla::Message::CharRightRectExtend, "Char Right Rect Extend" }, + { Scintilla::Message::HomeRectExtend, "Home Rect Extend" }, + { Scintilla::Message::VCHomeRectExtend, "VC Home Rect Extend" }, + { Scintilla::Message::LineEndRectExtend, "Line End Rect Extend" }, + { Scintilla::Message::PageUpRectExtend, "Page Up Rect Extend" }, + { Scintilla::Message::PageDownRectExtend, "Page Down Rect Extend" }, + { Scintilla::Message::SelectionDuplicate, "Selection Duplicate" }, + { Scintilla::Message::CopyAllowLine, "Copy Allow Line" }, + { Scintilla::Message::VerticalCentreCaret, "Vertical Centre Caret" }, + { Scintilla::Message::MoveSelectedLinesUp, "Move Selected Lines Up" }, + { Scintilla::Message::MoveSelectedLinesDown, "Move Selected Lines Down" }, + { Scintilla::Message::ScrollToStart, "Scroll To Start" }, + { Scintilla::Message::ScrollToEnd, "Scroll To End" } +}; + +MacroStep::MacroStep(Message message, uptr_t wParam, sptr_t lParam) : + message(message), + wParam(wParam) +{ + if (message == Message::ReplaceSel || message == Message::InsertText) { + // wParam is 0 for replace, and position for insert + this->str = QByteArray(reinterpret_cast(lParam)); + } + else if (message == Message::AddText || message == Message::AppendText) { + // wParam is length of text + this->str = QByteArray(reinterpret_cast(lParam), wParam); + } + else { + this->lParam = lParam; + } +} + +MacroStep::~MacroStep() +{ +} + +QString MacroStep::toString() const +{ + if (MacroStep::MessageHasString(message)) { + return QString("MacroStep(%1, %2, \"%3\")") + .arg(getName()) + .arg(wParam) + .arg(str.constData()); + } + else { + return QString("MacroStep(%1, %2, %3)") + .arg(getName()) + .arg(wParam) + .arg(lParam); + } +} + +QString MacroStep::getName() const +{ + return MacroStep::NameOfMessage(message); +} + +void MacroStep::replay(ScintillaNext *editor) const +{ + if (MacroStep::MessageHasString(message)) { + editor->sends(static_cast(message), wParam, str.constBegin()); + } + else { + editor->send(static_cast(message), wParam, lParam); + } +} + +bool MacroStep::MessageHasString(Scintilla::Message message) +{ + return message == Message::ReplaceSel || + message == Message::InsertText || + message == Message::AddText || + message == Message::AppendText; +} + +QString MacroStep::NameOfMessage(Scintilla::Message message) +{ + // Try to find the name in the known list + if (messageData.contains(message)) { + return messageData[message]; + } + else { + // Default to the list of enums + QMetaEnum metaEnum = QMetaEnum::fromType(); + return metaEnum.valueToKey(static_cast(message)); + } +} + +QList MacroStep::RecordableMacroMessages() +{ + return messageData.keys(); +} + +QDataStream &operator<<(QDataStream& stream, const MacroStep ¯oStep) +{ + // NOTE: Need to force the wParam and lParam into 32 bits due to Scintilla defining + // them differently on different systems. + + stream << macroStep.message << static_cast(macroStep.wParam); + + if (MacroStep::MessageHasString(macroStep.message)) + return stream << macroStep.str; + else + return stream << static_cast(macroStep.lParam); +} + +QDataStream &operator>>(QDataStream& stream, MacroStep ¯oStep) +{ + // NOTE: Need to force the wParam and lParam into 32 bits due to Scintilla defining + // them differently on different systems. + + quint32 w; + qint32 l; + + stream >> macroStep.message >> w; + macroStep.wParam = static_cast(w); + + if (MacroStep::MessageHasString(macroStep.message)) + return stream >> macroStep.str; + else { + stream >> l; + macroStep.lParam = static_cast(l); + return stream; + } +} diff --git a/src/NotepadNext/MacroStep.h b/src/NotepadNext/MacroStep.h new file mode 100644 index 000000000..52e45e0c2 --- /dev/null +++ b/src/NotepadNext/MacroStep.h @@ -0,0 +1,50 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MACROSTEP_H +#define MACROSTEP_H + +#include "ScintillaNext.h" + +class MacroStep { +public: + MacroStep() {} + MacroStep(Scintilla::Message message, uptr_t wParam, sptr_t lParam); + ~MacroStep(); + + QString toString() const; + QString getName() const; + + void replay(ScintillaNext *editor) const; + + friend QDataStream &operator<<(QDataStream& stream, const MacroStep ¯oStep); + friend QDataStream &operator>>(QDataStream& stream, MacroStep ¯oStep); + + static bool MessageHasString(Scintilla::Message message); + static QString NameOfMessage(Scintilla::Message message); + static QList RecordableMacroMessages(); + + Scintilla::Message message; + uptr_t wParam; + sptr_t lParam; + QByteArray str; +}; +Q_DECLARE_METATYPE(MacroStep) + +#endif // MACROSTEP_H diff --git a/src/NotepadNext/MacroStepTableModel.cpp b/src/NotepadNext/MacroStepTableModel.cpp new file mode 100644 index 000000000..35f157ce7 --- /dev/null +++ b/src/NotepadNext/MacroStepTableModel.cpp @@ -0,0 +1,192 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "MacroStepTableModel.h" + + +MacroStepTableModel::MacroStepTableModel(Macro *m, QObject *parent) : + QAbstractTableModel(parent), + macro(m) +{ +} + +QVariant MacroStepTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::DisplayRole) { + if (orientation == Qt::Horizontal) { + if (section == 0) + return tr("Name"); + else if (section == 1) + return tr("Text"); + } + } + + return QVariant(); +} + +int MacroStepTableModel::rowCount(const QModelIndex &parent) const +{ + return parent.isValid() ? 0 : macro->getSteps().size(); +} + +int MacroStepTableModel::columnCount(const QModelIndex &parent) const +{ + return parent.isValid() ? 0 : 2; +} + +QVariant MacroStepTableModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole) { + switch (index.column()) { + case 0: + if (role == Qt::EditRole) { + return static_cast(macro->getSteps()[index.row()].message); + } + else { + return macro->getSteps()[index.row()].getName(); + } + case 1: + return macro->getSteps()[index.row()].str; + default: + break; + } + } + + return QVariant(); +} + +bool MacroStepTableModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; + + if (role == Qt::EditRole) { + switch (index.column()) { + case 0: { + Scintilla::Message newMessage = static_cast(value.toInt()); + MacroStep &m = macro->getSteps()[index.row()]; + + m.message = newMessage; + + if (!MacroStep::MessageHasString(newMessage)) { + m.str.clear(); + } + + emit dataChanged(index, index, QVector() << role); + + return true; + } + case 1: + macro->getSteps()[index.row()].str = value.toString().toUtf8(); + + emit dataChanged(index, index, QVector() << role); + + return true; + default: + break; + } + } + + return false; +} + +bool MacroStepTableModel::insertRows(int row, int count, const QModelIndex &parent) +{ + if (count < 1 || row < 0 || row > rowCount(parent)) + return false; + + beginInsertRows(QModelIndex(), row, row + count - 1); + + for (int r = 0; r < count; ++r) { + macro->getSteps().insert(row, MacroStep(Scintilla::Message::ReplaceSel, 0, 0)); + } + + endInsertRows(); + + return true; +} + +bool MacroStepTableModel::removeRows(int row, int count, const QModelIndex &parent) +{ + Q_UNUSED(parent); + + beginRemoveRows(QModelIndex(), row, row + count - 1); + + macro->getSteps().remove(row, count); + + endRemoveRows(); + + return true; +} + +bool MacroStepTableModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) +{ + // Source code for this has been copied from QStringListModel::moveRows() + + if (sourceRow < 0 + || sourceRow + count - 1 >= rowCount(sourceParent) + || destinationChild <= 0 + || destinationChild > rowCount(destinationParent) + || sourceRow == destinationChild - 1 + || count <= 0) { + return false; + } + + if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), destinationChild)) + return false; + /* + QList::move assumes that the second argument is the index where the item will end up to + i.e. the valid range for that argument is from 0 to QList::size()-1 + QAbstractItemModel::moveRows when source and destinations have the same parent assumes that + the item will end up being in the row BEFORE the one indicated by destinationChild + i.e. the valid range for that argument is from 1 to QList::size() + For this reason we remove 1 from destinationChild when using it inside QList + */ + + destinationChild--; + + const int fromRow = destinationChild < sourceRow ? (sourceRow + count - 1) : sourceRow; + while (count--) + macro->getSteps().move(fromRow, destinationChild); + + endMoveRows(); + + return true; +} + +Qt::ItemFlags MacroStepTableModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + if (index.column() == 0) { + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; + } + else if (index.column() == 1 && MacroStep::MessageHasString(macro->getSteps()[index.row()].message)) { + // The second column is only editable if the macro has a string associated with it + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; + } + else { + return Qt::ItemIsEnabled; + } +} + diff --git a/src/NotepadNext/MacroStepTableModel.h b/src/NotepadNext/MacroStepTableModel.h new file mode 100644 index 000000000..430e84858 --- /dev/null +++ b/src/NotepadNext/MacroStepTableModel.h @@ -0,0 +1,48 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include + +#include "Macro.h" + +class MacroStepTableModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit MacroStepTableModel(Macro *m, QObject *parent = nullptr); + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + + bool insertRows(int row, int count, const QModelIndex &parent) override; + bool removeRows(int row, int count, const QModelIndex &parent) override; + + bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + +private: + Macro *macro; +}; diff --git a/src/NotepadNext/NotepadNext.pro b/src/NotepadNext/NotepadNext.pro new file mode 100644 index 000000000..1f1ced1fd --- /dev/null +++ b/src/NotepadNext/NotepadNext.pro @@ -0,0 +1,287 @@ +# This file is part of Notepad Next. +# Copyright 2019 Justin Dailey +# +# Notepad Next 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, either version 3 of the License, or +# (at your option) any later version. +# +# Notepad Next 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. +# +# You should have received a copy of the GNU General Public License +# along with Notepad Next. If not, see . + + +QT += core widgets printsupport network + +TARGET = NotepadNext + +TEMPLATE = app + +include(../Config.pri) + +include(../singleapplication/singleapplication.pri) +DEFINES += QAPPLICATION_CLASS=QApplication + + +include(../scintilla.pri) +include(../lexilla.pri) +include(../uchardet.pri) +include(../lua.pri) +include(../ads.pri) +include(../editorconfig-core-qt/EditorConfig.pri) +win32:include(../QSimpleUpdater/QSimpleUpdater.pri) +include(../i18n.pri) + +# Set variables for output executable +VERSION = $$APP_VERSION + +CONFIG += file_copies + +win32 { + QMAKE_TARGET_COMPANY = Notepad Next + QMAKE_TARGET_DESCRIPTION = Notepad Next + QMAKE_TARGET_COPYRIGHT = $$APP_COPYRIGHT + QMAKE_TARGET_PRODUCT = Notepad Next + RC_ICONS = ../../icon/NotepadNext.ico + + COPIES += openssl + openssl.files = $$files(../../deploy/windows/*.dll) + openssl.path = $$OUT_PWD +} + +macos { + QMAKE_INFO_PLIST = ../../deploy/macos/info.plist +} + +COPIES += license +license.files = ../../LICENSE +license.path = $$OUT_PWD + +SOURCES += \ + ApplicationSettings.cpp \ + ColorPickerDelegate.cpp \ + ComboBoxDelegate.cpp \ + Converter.cpp \ + DebugManager.cpp \ + DockedEditor.cpp \ + EditorHexViewerTableModel.cpp \ + EditorManager.cpp \ + EditorPrintPreviewRenderer.cpp \ + FadingIndicator.cpp \ + FileDialogHelpers.cpp \ + Finder.cpp \ + HtmlConverter.cpp \ + IFaceTable.cpp \ + IFaceTableMixer.cpp \ + LanguageStylesModel.cpp \ + LuaExtension.cpp \ + LuaState.cpp \ + Macro.cpp \ + MacroListModel.cpp \ + MacroManager.cpp \ + MacroRecorder.cpp \ + MacroStep.cpp \ + MacroStepTableModel.cpp \ + NotepadNextApplication.cpp \ + NppImporter.cpp \ + QRegexSearch.cpp \ + QuickFindWidget.cpp \ + RangeAllocator.cpp \ + RecentFilesListManager.cpp \ + RecentFilesListMenuBuilder.cpp \ + RtfConverter.cpp \ + SciIFaceTable.cpp \ + ScintillaCommenter.cpp \ + ScintillaNext.cpp \ + SearchResultsCollector.cpp \ + SelectionTracker.cpp \ + SessionManager.cpp \ + SpinBoxDelegate.cpp \ + TranslationManager.cpp \ + UndoAction.cpp \ + ZoomEventWatcher.cpp \ + decorators/ApplicationDecorator.cpp \ + decorators/AutoCompletion.cpp \ + decorators/AutoIndentation.cpp \ + decorators/BetterMultiSelection.cpp \ + decorators/BookMarkDecorator.cpp \ + decorators/EditorConfigAppDecorator.cpp \ + decorators/SurroundSelection.cpp \ + decorators/URLFinder.cpp \ + dialogs/ColumnEditorDialog.cpp \ + dialogs/MacroEditorDialog.cpp \ + docks/DebugLogDock.cpp \ + docks/EditorInspectorDock.cpp \ + dialogs/FindReplaceDialog.cpp \ + docks/FileListDock.cpp \ + docks/FolderAsWorkspaceDock.cpp \ + docks/HexViewerDock.cpp \ + docks/LanguageInspectorDock.cpp \ + docks/LuaConsoleDock.cpp \ + dialogs/MacroRunDialog.cpp \ + dialogs/MacroSaveDialog.cpp \ + dialogs/MainWindow.cpp \ + dialogs/PreferencesDialog.cpp \ + docks/SearchResultsDock.cpp \ + main.cpp \ + decorators/BraceMatch.cpp \ + decorators/EditorDecorator.cpp \ + decorators/HighlightedScrollBar.cpp \ + decorators/LineNumbers.cpp \ + decorators/SmartHighlighter.cpp \ + widgets/EditorInfoStatusBar.cpp \ + widgets/StatusLabel.cpp + +HEADERS += \ + ApplicationSettings.h \ + ColorPickerDelegate.h \ + ComboBoxDelegate.h \ + Converter.h \ + DebugManager.h \ + DockedEditor.h \ + DockedEditorTitleBar.h \ + EditorHexViewerTableModel.h \ + EditorManager.h \ + EditorPrintPreviewRenderer.h \ + FadingIndicator.h \ + FileDialogHelpers.h \ + Finder.h \ + FocusWatcher.h \ + HtmlConverter.h \ + IFaceTable.h \ + IFaceTableMixer.h \ + ISearchResultsHandler.h \ + LanguageStylesModel.h \ + LuaExtension.h \ + LuaState.h \ + Macro.h \ + MacroListModel.h \ + MacroManager.h \ + MacroRecorder.h \ + MacroStep.h \ + MacroStepTableModel.h \ + NotepadNextApplication.h \ + NppImporter.h \ + QRegexSearch.h \ + QuickFindWidget.h \ + RangeAllocator.h \ + RecentFilesListManager.h \ + RecentFilesListMenuBuilder.h \ + RtfConverter.h \ + SciIFaceTable.h \ + ScintillaCommenter.h \ + ScintillaEnums.h \ + ScintillaNext.h \ + SearchResultsCollector.h \ + SelectionTracker.h \ + SessionManager.h \ + SpinBoxDelegate.h \ + TranslationManager.h \ + UndoAction.h \ + ZoomEventWatcher.h \ + decorators/ApplicationDecorator.h \ + decorators/AutoCompletion.h \ + decorators/AutoIndentation.h \ + decorators/BetterMultiSelection.h \ + decorators/BookMarkDecorator.h \ + decorators/EditorConfigAppDecorator.h \ + decorators/SurroundSelection.h \ + decorators/URLFinder.h \ + dialogs/ColumnEditorDialog.h \ + dialogs/MacroEditorDialog.h \ + docks/DebugLogDock.h \ + docks/EditorInspectorDock.h \ + dialogs/FindReplaceDialog.h \ + docks/FileListDock.h \ + docks/FolderAsWorkspaceDock.h \ + docks/HexViewerDock.h \ + docks/LanguageInspectorDock.h \ + docks/LuaConsoleDock.h \ + dialogs/MacroRunDialog.h \ + dialogs/MacroSaveDialog.h \ + dialogs/MainWindow.h \ + dialogs/PreferencesDialog.h \ + decorators/BraceMatch.h \ + decorators/EditorDecorator.h \ + decorators/HighlightedScrollBar.h \ + decorators/LineNumbers.h \ + decorators/SmartHighlighter.h \ + docks/SearchResultsDock.h \ + widgets/EditorInfoStatusBar.h \ + widgets/StatusLabel.h + +FORMS += \ + QuickFindWidget.ui \ + dialogs/ColumnEditorDialog.ui \ + dialogs/MacroEditorDialog.ui \ + docks/DebugLogDock.ui \ + docks/EditorInspectorDock.ui \ + docks/FileListDock.ui \ + docks/FolderAsWorkspaceDock.ui \ + docks/HexViewerDock.ui \ + docks/LanguageInspectorDock.ui \ + dialogs/MainWindow.ui \ + dialogs/FindReplaceDialog.ui \ + docks/LuaConsoleDock.ui \ + dialogs/MacroRunDialog.ui \ + dialogs/MacroSaveDialog.ui \ + dialogs/PreferencesDialog.ui \ + docks/SearchResultsDock.ui + +RESOURCES += \ + resources.qrc \ + scripts.qrc \ + qdarkstyle/dark/style.qrc + +INCLUDEPATH += $$PWD/decorators +INCLUDEPATH += $$PWD/dialogs +INCLUDEPATH += $$PWD/docks +INCLUDEPATH += $$PWD/widgets + + +INCLUDEPATH += $$PWD/../LuaBridge +INCLUDEPATH += $$PWD/../ +DEFINES += LUA_VERSION_NUM=503 + +INCLUDEPATH += $$PWD/../lexilla/include + +win32-g++:LIBS += libUser32 +win32-msvc*:LIBS += User32.lib + +OBJECTS_DIR = build/obj +MOC_DIR = build/moc +RCC_DIR = build/qrc +UI_DIR = build/ui + +unix { + isEmpty(PREFIX) { + PREFIX = /usr + } + + target.path = $$PREFIX/bin + INSTALLS += target + + desktopfile.path = $$PREFIX/share/applications/ + desktopfile.files += ../../deploy/linux/NotepadNext.desktop + INSTALLS += desktopfile + + mimeicon.path = $$PREFIX/share/icons/hicolor/scalable/mimetypes/ + mimeicon.files = ../../icon/NotepadNext.svg + INSTALLS += mimeicon + + appicon.path = $$PREFIX/share/icons/hicolor/scalable/apps/ + appicon.files = ../../icon/NotepadNext.svg + INSTALLS += appicon +} + +macx: { + ICON = ../../icon/NotepadNext.icns + + versionAtLeast(QT_VERSION, 6.2) { + QMAKE_APPLE_DEVICE_ARCHS = x86_64 arm64 + } +} diff --git a/src/NotepadNext/NotepadNextApplication.cpp b/src/NotepadNext/NotepadNextApplication.cpp new file mode 100644 index 000000000..05ee9708d --- /dev/null +++ b/src/NotepadNext/NotepadNextApplication.cpp @@ -0,0 +1,568 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "MainWindow.h" +#include "NotepadNextApplication.h" +#include "RecentFilesListManager.h" +#include "EditorManager.h" +#include "LuaExtension.h" +#include "DebugManager.h" +#include "SessionManager.h" +#include "ThemeColors.h" +#include "TranslationManager.h" +#include "ApplicationSettings.h" + +#include "LuaState.h" +#include "lua.hpp" +#include "LuaBridge.h" + +#include "EditorConfigAppDecorator.h" + +#include "ILexer.h" +#include "Lexilla.h" + +#include + +#include + +#ifdef Q_OS_WIN +#include +#endif + +QString luaLanguagePath; + +const SingleApplication::Options opts = SingleApplication::ExcludeAppPath | SingleApplication::ExcludeAppVersion | SingleApplication::SecondaryNotification; + +template <> +struct luabridge::Stack +{ + static void push (lua_State* L, QString const &s) + { + lua_pushlstring(L, s.toLatin1().constData(), s.toLatin1().size()); + } + + static QString get (lua_State* L, int index) + { + return QString(luaL_checkstring (L, index)); + } +}; + +void parseCommandLine(QCommandLineParser &parser, const QStringList &args) +{ + parser.setApplicationDescription("Notepad Next"); + parser.addHelpOption(); + parser.addVersionOption(); + + parser.addPositionalArgument("files", "Files to open."); + + parser.addOptions({ + {"translation", "Overrides the system default translation.", "translation"}, + {"reset-settings", "Resets all application settings."}, + {"n", "Places the cursor on the line number for the first file specified", "line number"} + }); + + parser.process(args); +} + +static QString toLocalFileName(const QString file) +{ + QUrl fileUrl(file); + return fileUrl.isValid() && fileUrl.isLocalFile() ? fileUrl.toLocalFile() : file; +} + +NotepadNextApplication::NotepadNextApplication(int &argc, char **argv) + : SingleApplication(argc, argv, true, opts) +{ +#ifdef Q_OS_WIN + // Create a system-wide mutex so the installer can detect if it is running + CreateMutex(NULL, false, L"NotepadNextMutex"); +#endif + parseCommandLine(parser, arguments()); + + DebugManager::manageDebugOutput(); + DebugManager::pauseDebugOutput(); +} + +bool NotepadNextApplication::init() +{ + qInfo(Q_FUNC_INFO); + + setWindowIcon(QIcon(QStringLiteral(":/icons/NotepadNext.png"))); + + settings = new ApplicationSettings(this); + + if (parser.isSet("reset-settings")) { + settings->clear(); + } + + // Translation files are stored as a qresource + translationManager = new TranslationManager(this, QStringLiteral(":/i18n/")); + + // The command line overrides the settings + if (!parser.value("translation").isEmpty()) { + translationManager->loadTranslationByName(parser.value("translation")); + } + else { + // Normally the setting is "" which will load the default system translation + translationManager->loadTranslationByName(settings->translation()); + } + + // This connection isn't needed since the application can not appropriately retranslate the UI at runtime + //connect(settings, &ApplicationSettings::translationChanged, translationManager, &TranslationManager::loadTranslationByName); + + luaState = new LuaState(); + + recentFilesListManager = new RecentFilesListManager(this); + editorManager = new EditorManager(settings, this); + sessionManager = new SessionManager(this); + + connect(editorManager, &EditorManager::editorCreated, recentFilesListManager, [=](ScintillaNext *editor) { + if (editor->isFile()) { + recentFilesListManager->removeFile(editor->getFilePath()); + } + }); + + connect(editorManager, &EditorManager::editorClosed, recentFilesListManager, [=](ScintillaNext *editor) { + if (editor->isFile()) { + recentFilesListManager->addFile(editor->getFilePath()); + } + }); + + // why setting loaded here? can it be loaded eailer? + loadSettings(); + + bool darkMode = settings->darkMode(); + + // Set language path based on theme, + // dark mode may have its own path + //luaLanguagePath = darkMode ? "languages/dark" : "languages"; + luaLanguagePath = "languages"; // same language lua config for dark/light mode + qInfo("Dark mode: %d, Lua language path: %s", darkMode, qUtf8Printable(luaLanguagePath)); + + connect(this, &NotepadNextApplication::aboutToQuit, this, &NotepadNextApplication::saveSettings); + + EditorConfigAppDecorator *ecad = new EditorConfigAppDecorator(this); + ecad->setEnabled(true); + + // Set up colors language lua scripts, based on dark/light theme + setLanguageColors(); + + luaState->executeFile(":/scripts/init.lua"); + LuaExtension::Instance().Initialise(luaState->L, Q_NULLPTR); + + // LuaBridge is not a long term solution + // This is probably temporary, but it is quick and works + luabridge::setHideMetatables(false); + luabridge::getGlobalNamespace(luaState->L) + .beginNamespace("nn") + .beginClass("Settings") + .addFunction("showMenuBar", &ApplicationSettings::setShowMenuBar) + .addFunction("showToolBar", &ApplicationSettings::setShowToolBar) + .addFunction("showTabBar", &ApplicationSettings::setShowTabBar) + .addFunction("showStatusBar", &ApplicationSettings::setShowStatusBar) + .endClass() + .endNamespace(); + luabridge::setGlobal(luaState->L, settings, "settings"); + + createNewWindow(); + connect(editorManager, &EditorManager::editorCreated, window, &MainWindow::addEditor); + + luabridge::getGlobalNamespace(luaState->L) + .beginNamespace("nn") + .beginClass("QWidget") + .addFunction("exit", &QWidget::close) + .endClass() + .deriveClass("MainWindow") + .addFunction("newFile", &MainWindow::newFile) + .addFunction("openFile", &MainWindow::openFile) + .addFunction("openFileDialog", &MainWindow::openFileDialog) + .addFunction("reloadFile", &MainWindow::reloadFile) + .addFunction("saveFile", &MainWindow::saveCurrentFile) + .addFunction("saveFileAs", &MainWindow::saveCurrentFileAs) + .addFunction("closeFile", &MainWindow::closeCurrentFile) + .endClass() + .endNamespace(); + luabridge::setGlobal(luaState->L, window, "window"); + + // If the application is activated (e.g. user switching to another program and them back) the focus + // needs to be reset on whatever object previously had focus (e.g. the find dialog) + connect(this, &NotepadNextApplication::focusChanged, this, [&](QWidget *old, QWidget *now) { + Q_UNUSED(old); + if (now) { + currentlyFocusedWidget = now; + } + }); + + connect(this, &SingleApplication::instanceStarted, window, &MainWindow::bringWindowToForeground); + connect(this, &SingleApplication::receivedMessage, this, &NotepadNextApplication::receiveInfoFromSecondaryInstance, Qt::QueuedConnection); + + connect(this, &NotepadNextApplication::applicationStateChanged, this, [&](Qt::ApplicationState state) { + if (state == Qt::ApplicationActive) { + + // Make sure it is active... + // The application can be active without the main window being show e.g. if there is a + // message box that pops up before the main window + if (window->isActiveWindow()) { + window->focusIn(); + } + + if (!currentlyFocusedWidget.isNull()) { + currentlyFocusedWidget->activateWindow(); + } + } + }); + + if (settings->restorePreviousSession()) { + qInfo("Restoring previous session"); + + sessionManager->loadSession(window); + } + + openFiles(parser.positionalArguments()); + + if (parser.isSet("n") && parser.positionalArguments().length() > 0) { + QString firstFile = parser.positionalArguments()[0]; + ScintillaNext *editor = editorManager->getEditorByFilePath(toLocalFileName(firstFile)); + + if (editor) { + int n = parser.value("n").toInt(); + editor->gotoLine(n - 1); + } + } + + // If the window does not have any editors (meaning the no files were + // specified on the command line) then create a new empty file + if (window->editorCount() == 0) { + window->newFile(); + } + + // Everything should be ready at this point + + window->restoreWindowState(); + window->show(); + + DebugManager::resumeDebugOutput(); + + return true; +} + +SessionManager *NotepadNextApplication::getSessionManager() const +{ + SessionManager::SessionFileTypes fileTypes; + + if (settings->restorePreviousSession()) { + fileTypes |= SessionManager::SavedFile; + } + + if (settings->restoreUnsavedFiles()) { + fileTypes |= SessionManager::UnsavedFile; + } + + if (settings->restoreTempFiles()) { + fileTypes |= SessionManager::TempFile; + } + + // Update the file types supported in case something has changed in the settings + sessionManager->setSessionFileTypes(fileTypes); + + return sessionManager; +} + +QString NotepadNextApplication::getFileDialogFilter() const +{ + return getLuaState()->executeAndReturn("return DialogFilters()"); +} + +QString NotepadNextApplication::getFileDialogFilterForLanguage(const QString &language) const +{ + return getLuaState()->executeAndReturn(QString("return FilterForLanguage(\"%1\")").arg(language).toLatin1().constData()); +} + +QStringList NotepadNextApplication::getLanguages() const +{ + return getLuaState()->executeAndReturn( + R"( + local names = {} + for k in pairs(languages) do table.insert(names, k) end + table.sort(names, function (a, b) return string.lower(a) < string.lower(b) end) + return names + )"); +} + +void NotepadNextApplication::setEditorLanguage(ScintillaNext *editor, const QString &languageName) const +{ + LuaExtension::Instance().setEditor(editor); + + getLuaState()->execute(QString("languageName = \"%1\"").arg(languageName)); + const QString lexer = getLuaState()->executeAndReturn("return languages[languageName].lexer"); + + editor->languageName = languageName; + editor->languageSingleLineComment = getLuaState()->executeAndReturn("return languages[languageName].singleLineComment or \"\"").toUtf8(); + + auto lexerInstance = CreateLexer(lexer.toLatin1().constData()); + editor->setILexer((sptr_t) lexerInstance); + editor->clearDocumentStyle(); // Remove all previous style information, setting the lexer does not guarantee styling information is cleared + + // Not ideal this has to be manually emitted but it works since setILexer() is not widely used + emit editor->lexerChanged(); + + // Dynamic properties can be used to skip part of the default initialization. The value in the + // property doesn't currently matter, but may be used at a later point. + getLuaState()->execute(QString("skip_tabs = %1").arg(editor->QObject::property("nn_skip_usetabs").isValid() ? "true" : "false")); + getLuaState()->execute(QString("skip_tabwidth = %1").arg(editor->QObject::property("nn_skip_tabwidth").isValid() ? "true" : "false")); + + getLuaState()->execute(R"( + local L = languages[languageName] + + if not skip_tabs then + editor.UseTabs = (L.tabSettings or "tabs") == "tabs" + end + if not skip_tabwidth then + editor.TabWidth = L.tabSize or 4 + end + + editor.MarginWidthN[2] = L.disableFoldMargin and 0 or 16 + if L.styles then + for name, style in pairs(L.styles) do + editor.StyleFore[style.id] = style.fgColor + editor.StyleBack[style.id] = style.bgColor + + if style.fontStyle then + editor.StyleBold[style.id] = (style.fontStyle & 1 == 1) + editor.StyleItalic[style.id] = (style.fontStyle & 2 == 2) + editor.StyleUnderline[style.id] = (style.fontStyle & 4 == 4) + editor.StyleEOLFilled[style.id] = (style.fontStyle & 8 == 8) + end + end + end + if L.keywords then + for id, kw in pairs(L.keywords) do + editor.KeyWords[id] = kw + end + end + if L.properties then + for p,v in pairs(L.properties) do + editor.Property[p] = v + end + end + + editor.Property["fold"] = "1" + editor.Property["fold.compact"] = "0" + )"); +} + +QString NotepadNextApplication::detectLanguage(ScintillaNext *editor) const +{ + qInfo(Q_FUNC_INFO); + + QString language_name = QStringLiteral("Text"); + + if (editor->isFile()) { + language_name = detectLanguageFromExtension(editor->getFileInfo().suffix()); + } + + if (language_name == QStringLiteral("Text")) { + language_name = detectLanguageFromContents(editor); + } + + return language_name; +} + +QString NotepadNextApplication::detectLanguageFromExtension(const QString &extension) const +{ + qInfo(Q_FUNC_INFO); + + return getLuaState()->executeAndReturn(QString(R"( + local ext = "%1" + for name, L in pairs(languages) do + if L.extensions then + for _, v in ipairs(L.extensions) do + if v == ext then + return name + end + end + end + end + return "Text" + )").arg(extension).toLatin1().constData()); +} + +QString NotepadNextApplication::detectLanguageFromContents(ScintillaNext *editor) const +{ + qInfo(Q_FUNC_INFO); + + LuaExtension::Instance().setEditor(editor); + + return getLuaState()->executeAndReturn(QString(R"( + -- Grab a small chunk + if editor.Length > 0 then + editor:SetTargetRange(0, math.min(64, editor.Length)) + return detectLanguageFromContents(editor.TargetText) + end + + return "Text" + )").toLatin1().constData()); +} + +void NotepadNextApplication::sendInfoToPrimaryInstance() +{ + qInfo(Q_FUNC_INFO); + + QByteArray buffer; + QDataStream stream(&buffer, QIODevice::WriteOnly); + + stream << arguments(); + const bool success = sendMessage(buffer); + + if (!success) { + qWarning("sendMessage() unsuccessful"); + } +} + +void NotepadNextApplication::receiveInfoFromSecondaryInstance(quint32 instanceId, QByteArray message) +{ + qInfo(Q_FUNC_INFO); + + Q_UNUSED(instanceId) + + QDataStream stream(&message, QIODevice::ReadOnly); + QStringList args; + + stream >> args; + + QCommandLineParser parser; + parseCommandLine(parser, args); + + openFiles(parser.positionalArguments()); +} + +bool NotepadNextApplication::isRunningAsAdmin() const +{ + static bool initialized = false; + static bool isAdmin = false; + + if (!initialized) { + initialized = true; + +#ifdef Q_OS_WIN + BOOL isMember; + SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; + PSID administratorsGroupSid = NULL; + + // Create a SID for the Administrators group + if (AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &administratorsGroupSid)) { + if (CheckTokenMembership(NULL, administratorsGroupSid, &isMember)) { + isAdmin = isMember; + } + FreeSid(administratorsGroupSid); + } +#endif + } + + return isAdmin; +} + +bool NotepadNextApplication::event(QEvent *event) +{ + // Handle the QFileOpenEvent to open files on MacOS X. + if (event->type() == QEvent::FileOpen) { + QFileOpenEvent *fileOpenEvent = static_cast(event); + + qInfo("QFileOpenEvent %s", qUtf8Printable(fileOpenEvent->file())); + + openFiles(QStringList() << fileOpenEvent->file()); + + return true; + } + + return SingleApplication::event(event); +} + +void NotepadNextApplication::openFiles(const QStringList &files) +{ + qInfo(Q_FUNC_INFO); + + for (const QString &file : files) { + window->openFile(toLocalFileName(file)); + } +} + +void NotepadNextApplication::loadSettings() +{ + recentFilesListManager->setFileList(getSettings()->value("App/RecentFilesList").toStringList()); +} + +void NotepadNextApplication::saveSettings() +{ + getSettings()->setValue("App/RecentFilesList", recentFilesListManager->fileList()); +} + +MainWindow *NotepadNextApplication::createNewWindow() +{ + Q_ASSERT(window == Q_NULLPTR); + + window = new MainWindow(this); + + // Keep Lua's editor reference up to date + connect(window, &MainWindow::editorActivated, this, [](ScintillaNext *editor) { + LuaExtension::Instance().setEditor(editor); + }); + + // Since these editors don't actually get "closed" go ahead and add them to the recent file list + connect(window, &MainWindow::aboutToClose, this, [=]() { + for (const auto &editor : window->editors()) { + if (editor->isFile()) { + recentFilesListManager->addFile(editor->getFilePath()); + } + } + + getSessionManager()->saveSession(window); + }); + + return window; +} + +/** + * Build a Lua assignment statement: var = rgb + */ +static QString buildLuaAssignment(QString var, long rgb) +{ + return QString("%1=0x%2").arg(var).arg(rgb2bgr(rgb), 0, 16); +} + +/** + * Set languages colors based dark/light mode settings + */ +void NotepadNextApplication::setLanguageColors() +{ + bool darkMode = settings->darkMode(); + + // Set language highlighting colors based on theme + long defaultFgColor = darkMode ? DARK_DEFAULT_FG : LIGHT_DEFAULT_FG; + long defaultBgColor = darkMode ? DARK_DEFAULT_BG : LIGHT_DEFAULT_BG; + long instructionColor= darkMode ? DARK_INTRUCTION_COLOR : LIGHT_INTRUCTION_COLOR; + long operatorColor = darkMode ? DARK_OPERATOR_COLOR : LIGHT_OPERATOR_COLOR; + long typeColor = darkMode ? DARK_TYPE_COLOR : LIGHT_TYPE_COLOR; + + luaState->execute(buildLuaAssignment("defaultFg", defaultFgColor)); + luaState->execute(buildLuaAssignment("defaultBg", defaultBgColor)); + luaState->execute(buildLuaAssignment("InstructionColor", instructionColor)); + luaState->execute(buildLuaAssignment("OperatorColor", operatorColor)); + luaState->execute(buildLuaAssignment("TypeColor", typeColor)); +} diff --git a/src/NotepadNext/NotepadNextApplication.h b/src/NotepadNext/NotepadNextApplication.h new file mode 100644 index 000000000..600e83eef --- /dev/null +++ b/src/NotepadNext/NotepadNextApplication.h @@ -0,0 +1,101 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef NOTEPADNEXTAPPLICATION_H +#define NOTEPADNEXTAPPLICATION_H + +#include "ApplicationSettings.h" + +#include "SingleApplication" + +#include +#include + + +class MainWindow; +class LuaState; +class EditorManager; +class RecentFilesListManager; +class ScintillaNext; +class SessionManager; +class TranslationManager; + + +class NotepadNextApplication : public SingleApplication +{ + Q_OBJECT + +public: + NotepadNextApplication(int &argc, char **argv); + + bool init(); + + RecentFilesListManager *getRecentFilesListManager() const { return recentFilesListManager; } + EditorManager *getEditorManager() const { return editorManager; } + SessionManager *getSessionManager() const; + TranslationManager *getTranslationManager() const { return translationManager; }; + + LuaState *getLuaState() const { return luaState; } + QString getFileDialogFilter() const; + QString getFileDialogFilterForLanguage(const QString &language) const; + ApplicationSettings *getSettings() const { return settings; } + + QStringList getLanguages() const; + void setEditorLanguage(ScintillaNext *editor, const QString &languageName) const; + + QString detectLanguage(ScintillaNext *editor) const; + QString detectLanguageFromExtension(const QString &extension) const; + QString detectLanguageFromContents(ScintillaNext *editor) const; + + void sendInfoToPrimaryInstance(); + + // expose this method to make it possible to change theme without restart + void setLanguageColors(); + + bool isRunningAsAdmin() const; + +protected: + bool event(QEvent *event) override; + +private slots: + void saveSettings(); + void receiveInfoFromSecondaryInstance(quint32 instanceId, QByteArray message); + +private: + void openFiles(const QStringList &files); + + void loadSettings(); + + EditorManager *editorManager; + RecentFilesListManager *recentFilesListManager; + ApplicationSettings *settings; + SessionManager *sessionManager; + TranslationManager *translationManager; + + LuaState *luaState = Q_NULLPTR; + + MainWindow *window = Q_NULLPTR; + QPointer currentlyFocusedWidget; // Keep a weak pointer to the QWidget since we don't own it + + MainWindow *createNewWindow(); + + QCommandLineParser parser; +}; + +#endif // NOTEPADNEXTAPPLICATION_H diff --git a/src/NotepadNext/NppImporter.cpp b/src/NotepadNext/NppImporter.cpp new file mode 100644 index 000000000..129ade77c --- /dev/null +++ b/src/NotepadNext/NppImporter.cpp @@ -0,0 +1,433 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + + +#include +#include + +#include "NppImporter.h" +#include "SciLexer.h" + +#define FONTSTYLE_BOLD 1 +#define FONTSTYLE_ITALIC 2 +#define FONTSTYLE_UNDERLINE 4 + +static inline int color(int c) { + return (c & 0xFF0000) >> 16 | (c & 0x00FF00) | (c & 0x0000FF) << 16; +} + +const int LANG_INDEX_INSTR = 0; +const int LANG_INDEX_INSTR2 = 1; +const int LANG_INDEX_TYPE = 2; +const int LANG_INDEX_TYPE2 = 3; +const int LANG_INDEX_TYPE3 = 4; +const int LANG_INDEX_TYPE4 = 5; +const int LANG_INDEX_TYPE5 = 6; + +static int keywordClassToIndex(const QStringView keywordClass) +{ + if (keywordClass == QStringLiteral("instre1")) return LANG_INDEX_INSTR; + if (keywordClass == QStringLiteral("instre2")) return LANG_INDEX_INSTR2; + if (keywordClass == QStringLiteral("type1")) return LANG_INDEX_TYPE; + if (keywordClass == QStringLiteral("type2")) return LANG_INDEX_TYPE2; + if (keywordClass == QStringLiteral("type3")) return LANG_INDEX_TYPE3; + if (keywordClass == QStringLiteral("type4")) return LANG_INDEX_TYPE4; + if (keywordClass == QStringLiteral("type5")) return LANG_INDEX_TYPE5; + return -1; // TODO: not sure what is best +} +struct LanguageName { + QString shortName; + QString longName; + int lexer_id; +}; + +#define TEXT(x) x +static const QMap langNamesToLexer = { + {TEXT("normal"), {TEXT("Normal text"), TEXT("Normal text file"), SCLEX_NULL}}, + {TEXT("php"), {TEXT("PHP"), TEXT("PHP Hypertext Preprocessor file"), SCLEX_HTML}}, + {TEXT("c"), {TEXT("C"), TEXT("C source file"), SCLEX_CPP}}, + {TEXT("cpp"), {TEXT("C++"), TEXT("C++ source file"), SCLEX_CPP}}, + {TEXT("cs"), {TEXT("C#"), TEXT("C# source file"), SCLEX_CPP}}, + {TEXT("objc"), {TEXT("Objective-C"), TEXT("Objective-C source file"), SCLEX_CPP}}, + {TEXT("java"), {TEXT("Java"), TEXT("Java source file"), SCLEX_CPP}}, + {TEXT("rc"), {TEXT("RC"), TEXT("Windows Resource file"), SCLEX_CPP}}, + {TEXT("html"), {TEXT("HTML"), TEXT("Hyper Text Markup Language file"), SCLEX_HTML}}, + {TEXT("xml"), {TEXT("XML"), TEXT("eXtensible Markup Language file"), SCLEX_XML}}, + {TEXT("makefile"), {TEXT("Makefile"), TEXT("Makefile"), SCLEX_MAKEFILE}}, + {TEXT("pascal"), {TEXT("Pascal"), TEXT("Pascal source file"), SCLEX_PASCAL}}, + {TEXT("batch"), {TEXT("Batch"), TEXT("Batch file"), SCLEX_BATCH}}, + {TEXT("ini"), {TEXT("ini"), TEXT("MS ini file"), SCLEX_PROPERTIES}}, + {TEXT("nfo"), {TEXT("NFO"), TEXT("MSDOS Style/ASCII Art"), SCLEX_NULL}}, + //{TEXT("udf"), {TEXT("udf"), TEXT("User Define File"), SCLEX_USER}}, + {TEXT("asp"), {TEXT("ASP"), TEXT("Active Server Pages script file"), SCLEX_HTML}}, + {TEXT("sql"), {TEXT("SQL"), TEXT("Structured Query Language file"), SCLEX_SQL}}, + {TEXT("vb"), {TEXT("Visual Basic"), TEXT("Visual Basic file"), SCLEX_VB}}, + {TEXT("javascript"), {TEXT("JavaScript"), TEXT("JavaScript file"), SCLEX_CPP}}, + {TEXT("css"), {TEXT("CSS"), TEXT("Cascade Style Sheets File"), SCLEX_CSS}}, + {TEXT("perl"), {TEXT("Perl"), TEXT("Perl source file"), SCLEX_PERL}}, + {TEXT("python"), {TEXT("Python"), TEXT("Python file"), SCLEX_PYTHON}}, + {TEXT("lua"), {TEXT("Lua"), TEXT("Lua source File"), SCLEX_LUA}}, + {TEXT("tex"), {TEXT("TeX"), TEXT("TeX file"), SCLEX_TEX}}, + {TEXT("fortran"), {TEXT("Fortran free form"), TEXT("Fortran free form source file"), SCLEX_FORTRAN}}, + {TEXT("bash"), {TEXT("Shell"), TEXT("Unix script file"), SCLEX_BASH}}, + {TEXT("actionscript"), {TEXT("ActionScript"), TEXT("Flash ActionScript file"), SCLEX_CPP}}, + {TEXT("nsis"), {TEXT("NSIS"), TEXT("Nullsoft Scriptable Install System script file"), SCLEX_NSIS}}, + {TEXT("tcl"), {TEXT("TCL"), TEXT("Tool Command Language file"), SCLEX_TCL}}, + {TEXT("lisp"), {TEXT("Lisp"), TEXT("List Processing language file"), SCLEX_LISP}}, + {TEXT("scheme"), {TEXT("Scheme"), TEXT("Scheme file"), SCLEX_LISP}}, + {TEXT("asm"), {TEXT("Assembly"), TEXT("Assembly language source file"), SCLEX_ASM}}, + {TEXT("diff"), {TEXT("Diff"), TEXT("Diff file"), SCLEX_DIFF}}, + {TEXT("props"), {TEXT("Properties file"), TEXT("Properties file"), SCLEX_PROPERTIES}}, + {TEXT("postscript"), {TEXT("PostScript"), TEXT("PostScript file"), SCLEX_PS}}, + {TEXT("ruby"), {TEXT("Ruby"), TEXT("Ruby file"), SCLEX_RUBY}}, + {TEXT("smalltalk"), {TEXT("Smalltalk"), TEXT("Smalltalk file"), SCLEX_SMALLTALK}}, + {TEXT("vhdl"), {TEXT("VHDL"), TEXT("VHSIC Hardware Description Language file"), SCLEX_VHDL}}, + {TEXT("kix"), {TEXT("KiXtart"), TEXT("KiXtart file"), SCLEX_KIX}}, + {TEXT("autoit"), {TEXT("AutoIt"), TEXT("AutoIt"), SCLEX_AU3}}, + {TEXT("caml"), {TEXT("CAML"), TEXT("Categorical Abstract Machine Language"), SCLEX_CAML}}, + {TEXT("ada"), {TEXT("Ada"), TEXT("Ada file"), SCLEX_ADA}}, + {TEXT("verilog"), {TEXT("Verilog"), TEXT("Verilog file"), SCLEX_VERILOG}}, + {TEXT("matlab"), {TEXT("MATLAB"), TEXT("MATrix LABoratory"), SCLEX_MATLAB}}, + {TEXT("haskell"), {TEXT("Haskell"), TEXT("Haskell"), SCLEX_HASKELL}}, + {TEXT("inno"), {TEXT("Inno Setup"), TEXT("Inno Setup script"), SCLEX_INNOSETUP}}, + //{TEXT("searchResult"), {TEXT("Internal Search"), TEXT("Internal Search"), SCLEX_SEARCHRESULT}}, + {TEXT("cmake"), {TEXT("CMake"), TEXT("CMake file"), SCLEX_CMAKE}}, + {TEXT("yaml"), {TEXT("YAML"), TEXT("YAML Ain't Markup Language"), SCLEX_YAML}}, + {TEXT("cobol"), {TEXT("COBOL"), TEXT("COmmon Business Oriented Language"), SCLEX_COBOL}}, + {TEXT("gui4cli"), {TEXT("Gui4Cli"), TEXT("Gui4Cli file"), SCLEX_GUI4CLI}}, + {TEXT("d"), {TEXT("D"), TEXT("D programming language"), SCLEX_D}}, + {TEXT("powershell"), {TEXT("PowerShell"), TEXT("Windows PowerShell"), SCLEX_POWERSHELL}}, + {TEXT("r"), {TEXT("R"), TEXT("R programming language"), SCLEX_R}}, + {TEXT("jsp"), {TEXT("JSP"), TEXT("JavaServer Pages script file"), SCLEX_HTML}}, + {TEXT("coffeescript"), {TEXT("CoffeeScript"), TEXT("CoffeeScript file"), SCLEX_COFFEESCRIPT}}, + {TEXT("json"), {TEXT("json"), TEXT("JSON file"), SCLEX_CPP }}, + {TEXT("javascript.js"), {TEXT("JavaScript"), TEXT("JavaScript file"), SCLEX_CPP }}, + {TEXT("fortran77"), {TEXT("Fortran fixed form"), TEXT("Fortran fixed form source file"), SCLEX_F77}}, + {TEXT("baanc"), {TEXT("BaanC"), TEXT("BaanC File"), SCLEX_BAAN }}, + {TEXT("srec"), {TEXT("S-Record"), TEXT("Motorola S-Record binary data"), SCLEX_SREC}}, + {TEXT("ihex"), {TEXT("Intel HEX"), TEXT("Intel HEX binary data"), SCLEX_IHEX}}, + {TEXT("tehex"), {TEXT("Tektronix extended HEX"), TEXT("Tektronix extended HEX binary data"), SCLEX_TEHEX}}, + {TEXT("swift"), {TEXT("Swift"), TEXT("Swift file"), SCLEX_CPP}}, + {TEXT("asn1"), {TEXT("ASN.1"), TEXT("Abstract Syntax Notation One file"), SCLEX_ASN1}}, + {TEXT("avs"), {TEXT("AviSynth"), TEXT("AviSynth scripts files"), SCLEX_AVS}}, + {TEXT("blitzbasic"), {TEXT("BlitzBasic"), TEXT("BlitzBasic file"), SCLEX_BLITZBASIC}}, + {TEXT("purebasic"), {TEXT("PureBasic"), TEXT("PureBasic file"), SCLEX_PUREBASIC}}, + {TEXT("freebasic"), {TEXT("FreeBasic"), TEXT("FreeBasic file"), SCLEX_FREEBASIC}}, + {TEXT("csound"), {TEXT("Csound"), TEXT("Csound file"), SCLEX_CSOUND}}, + {TEXT("erlang"), {TEXT("Erlang"), TEXT("Erlang file"), SCLEX_ERLANG}}, + {TEXT("escript"), {TEXT("ESCRIPT"), TEXT("ESCRIPT file"), SCLEX_ESCRIPT}}, + {TEXT("forth"), {TEXT("Forth"), TEXT("Forth file"), SCLEX_FORTH}}, + {TEXT("latex"), {TEXT("LaTeX"), TEXT("LaTeX file"), SCLEX_LATEX}}, + {TEXT("mmixal"), {TEXT("MMIXAL"), TEXT("MMIXAL file"), SCLEX_MMIXAL}}, + {TEXT("nimrod"), {TEXT("Nimrod"), TEXT("Nimrod file"), SCLEX_NIMROD}}, + {TEXT("nncrontab"), {TEXT("Nncrontab"), TEXT("extended crontab file"), SCLEX_NNCRONTAB}}, + {TEXT("oscript"), {TEXT("OScript"), TEXT("OScript source file"), SCLEX_OSCRIPT}}, + {TEXT("rebol"), {TEXT("REBOL"), TEXT("REBOL file"), SCLEX_REBOL}}, + {TEXT("registry"), {TEXT("registry"), TEXT("registry file"), SCLEX_REGISTRY}}, + {TEXT("rust"), {TEXT("Rust"), TEXT("Rust file"), SCLEX_RUST}}, + {TEXT("spice"), {TEXT("Spice"), TEXT("spice file"), SCLEX_SPICE}}, + {TEXT("txt2tags"), {TEXT("txt2tags"), TEXT("txt2tags file"), SCLEX_TXT2TAGS}}, + {TEXT("ext"), {TEXT("External"), TEXT("External"), SCLEX_NULL}} +}; + +static const QMap> folderMarkers = { + {"type", {SC_MARKNUM_FOLDEROPEN, SC_MARKNUM_FOLDER, SC_MARKNUM_FOLDERSUB, SC_MARKNUM_FOLDERTAIL, SC_MARKNUM_FOLDEREND, SC_MARKNUM_FOLDEROPENMID, SC_MARKNUM_FOLDERMIDTAIL}}, + {"simple", {SC_MARK_MINUS, SC_MARK_PLUS, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY}}, + {"arrow", {SC_MARK_ARROWDOWN, SC_MARK_ARROW, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY}}, + {"circle", {SC_MARK_CIRCLEMINUS, SC_MARK_CIRCLEPLUS,SC_MARK_VLINE, SC_MARK_LCORNERCURVE, SC_MARK_CIRCLEPLUSCONNECTED, SC_MARK_CIRCLEMINUSCONNECTED, SC_MARK_TCORNERCURVE}}, + {"box", {SC_MARK_BOXMINUS, SC_MARK_BOXPLUS, SC_MARK_VLINE, SC_MARK_LCORNER, SC_MARK_BOXPLUSCONNECTED, SC_MARK_BOXMINUSCONNECTED, SC_MARK_TCORNER}} +}; + +NppImporter::NppImporter(const QString &configPath, ScintillaEdit *_editor) : + editor(_editor) +{ + qInfo("Import Notepad++ settings from: \"%s\"", qUtf8Printable(configPath)); + + if (!QFile::exists(configPath)) { + qInfo("import location not found"); + return; + } + + QDir dir(configPath); + + readLangsModel(dir.filePath("langs.xml")); + readStylersModel(dir.filePath("stylers.xml")); + readConfigModel(dir.filePath("config.xml")); + + // Do some cleanup because I have no idea what Notepad++ is doing in some cases + languages["cpp"].keywords[LANG_INDEX_INSTR2] = languages["cpp"].keywords.take(LANG_INDEX_TYPE); + languages["cpp"].lexer.styles[16].keywordClass = LANG_INDEX_INSTR2; + + + // Build a temporary list of the key/value pairs + QList> sortedLanguages; + for (const QString &key : languages.keys()) { + sortedLanguages.append(qMakePair(key, &languages[key])); + } + // And sort it based on the values + std::sort(sortedLanguages.begin(), sortedLanguages.end(), [](const QPair &a, const QPair &b) { + return QString::compare(a.second->shortName, b.second->shortName, Qt::CaseInsensitive) < 0; + }); + + // Store the sorted keys + for (const QPair &pair : sortedLanguages) { + sortedLanguageKeys.append(pair.first); + } +} + +void NppImporter::readLangsModel(const QString &filePath) +{ + QFile file(filePath); + + if (file.open(QIODevice::ReadOnly)) { + QXmlStreamReader xml(&file); + + xml.readNextStartElement(); + while (xml.readNextStartElement()) { + if (xml.name() == QStringLiteral("Languages")) { + //qInfo(qUtf8Printable(xml.name().toString())); + + while (xml.readNextStartElement()) { + auto attrs = xml.attributes(); + if (!langNamesToLexer.contains(attrs.value("name").toString())) { + xml.skipCurrentElement(); + continue; + } + + Language language; + language.name = attrs.value("name").toString(); + language.extensions = attrs.value("ext").toString().split(" ", Qt::SkipEmptyParts); + language.shortName = langNamesToLexer[language.name].shortName; + language.longDescription = langNamesToLexer[language.name].longName; + language.lexer_id = langNamesToLexer[language.name].lexer_id; + // TODO: read more + while (xml.readNextStartElement()) { + //qInfo(qUtf8Printable(language.name)); + auto attrs = xml.attributes(); + auto t = xml.readElementText(); + //qInfo(qUtf8Printable(t)); + language.keywords[keywordClassToIndex(attrs.value("name"))] = t; + //xml.skipCurrentElement(); + } + languages.insert(language.name, language); + } + } + else { + xml.skipCurrentElement(); + } + } + if (xml.hasError()) { + qWarning("%s", qUtf8Printable(xml.errorString())); + } + } +} + +void NppImporter::readStylersModel(const QString &filePath) +{ + QFile file(filePath); + + if (file.open(QIODevice::ReadOnly)) { + QXmlStreamReader xml(&file); + + xml.readNextStartElement(); + while (xml.readNextStartElement()) { + if (xml.name() == QStringLiteral("LexerStyles")) { + readLexerStyles(xml); + } + else if (xml.name() == QStringLiteral("GlobalStyles")) { + readGlobalStyles(xml); + } + else { + xml.skipCurrentElement(); + } + } + if (xml.hasError()) { + qWarning("%s", qUtf8Printable(xml.errorString())); + } + } +} + +void NppImporter::readConfigModel(const QString &filePath) +{ + QFile file(filePath); + + if (file.open(QIODevice::ReadOnly)) { + QXmlStreamReader xml(&file); + + xml.readNextStartElement(); + while (xml.readNextStartElement()) { + if (xml.name() == QStringLiteral("GUIConfigs")) { + readGUIConfigs(xml); + } + else { + xml.skipCurrentElement(); + } + } + if (xml.hasError()) { + qWarning("%s", qUtf8Printable(xml.errorString())); + } + } +} + +void NppImporter::readLexerStyles(QXmlStreamReader &xml) +{ + qInfo("%s", qUtf8Printable(xml.name().toString())); + + while (xml.readNextStartElement()) { + auto attrs = xml.attributes(); + if (!langNamesToLexer.contains(attrs.value("name").toString())) { + xml.skipCurrentElement(); + continue; + } + + LexerType *lexer = &languages[attrs.value("name").toString()].lexer; + lexer->description = attrs.value("desc").toString(); + while (xml.readNextStartElement()) { + //qInfo(qUtf8Printable(xml.name().toString())); + auto attrs = xml.attributes(); + LexerStyle style; + style.id = attrs.value("styleID").toInt(); + style.fgColor = color(attrs.value("fgColor").toInt(nullptr, 16)); + style.bgColor = color(attrs.value("bgColor").toInt(nullptr, 16)); + if (attrs.hasAttribute("keywordClass")) { + style.keywordClass = keywordClassToIndex(attrs.value("keywordClass")); + } + else { + style.keywordClass = -1; + } + lexer->styles.append(style); + xml.skipCurrentElement(); + } + } +} + +void NppImporter::readGlobalStyles(QXmlStreamReader &xml) +{ + editor->setMarginWidthN(0, 30); + editor->styleResetDefault(); + editor->styleClearAll(); + + while (xml.readNextStartElement()) { + //qInfo(qUtf8Printable(xml.tokenString())); + //qInfo(qUtf8Printable(xml.attributes().value("name").toString())); + + auto attrs = xml.attributes(); + int styleID = attrs.value("styleID").toInt(); + if (styleID >= 32 && styleID <= 39) { + int fgColor = attrs.value("fgColor").toInt(nullptr, 16); + int bgColor = attrs.value("bgColor").toInt(nullptr, 16); + + editor->styleSetFore(styleID, color(fgColor)); + editor->styleSetBack(styleID, color(bgColor)); + + if (attrs.hasAttribute("fontName") && attrs.value("fontName").length() > 0) { + editor->styleSetFont(styleID, attrs.value("fontName").toLocal8Bit().constData()); + } + if (attrs.hasAttribute("fontSize") && attrs.value("fontSize").length() > 0) { + int fontSize = attrs.value("fontSize").toInt(); + editor->styleSetSize(styleID, fontSize); + } + if (attrs.hasAttribute("fontStyle") && attrs.value("fontStyle").length() > 0) { + int fontStyle = attrs.value("fontStyle").toInt(); + editor->styleSetBold(styleID, fontStyle & FONTSTYLE_BOLD); + editor->styleSetItalic(styleID, fontStyle & FONTSTYLE_ITALIC); + editor->styleSetUnderline(styleID, fontStyle & FONTSTYLE_UNDERLINE); + } + if (styleID == STYLE_DEFAULT) { + editor->styleClearAll(); + } + } + else if (styleID > 0) { + editor->indicSetFore(styleID, color(attrs.value("bgColor").toInt(nullptr, 16))); + } + else if (attrs.value("name") == QStringLiteral("Current line background colour")) { + editor->setCaretLineBack(color(attrs.value("bgColor").toInt(nullptr, 16))); + } + else if (attrs.value("name") == QStringLiteral("Selected text colour")) { + editor->setSelBack(true, color(attrs.value("bgColor").toInt(nullptr, 16))); + } + else if (attrs.value("name") == QStringLiteral("Caret colour")) { + editor->setCaretFore(color(attrs.value("fgColor").toInt(nullptr, 16))); + } + else if (attrs.value("name") == QStringLiteral("Edge colour")) { + editor->setEdgeColour(color(attrs.value("fgColor").toInt(nullptr, 16))); + } + else if (attrs.value("name") == QStringLiteral("White space symbol")) { + editor->setWhitespaceFore(true, color(attrs.value("fgColor").toInt(nullptr, 16))); + } + else if (attrs.value("name") == QStringLiteral("Fold")) { + // NOTE: Yes this is a bug in Notepad++ swapping the fg and bg colors + foldFgColor = color(attrs.value("bgColor").toInt(nullptr, 16)); + foldBgColor = color(attrs.value("fgColor").toInt(nullptr, 16)); + } + else if (attrs.value("name") == QStringLiteral("Fold active")) { + activeFgColor = color(attrs.value("fgColor").toInt(nullptr, 16)); + } + else if (attrs.value("name") == QStringLiteral("Fold margin")) { + editor->setFoldMarginColour(true, color(attrs.value("fgColor").toInt(nullptr, 16))); + editor->setFoldMarginHiColour(true, color(attrs.value("bgColor").toInt(nullptr, 16))); + } + else { + //qWarning("Unhandled WidgetStyle \"%s\"", qUtf8Printable(xml.attributes().value("name").toString())); + } + xml.skipCurrentElement(); + } +} + +void NppImporter::readGUIConfigs(QXmlStreamReader &xml) +{ + while (xml.readNextStartElement()) { + auto attrs = xml.attributes(); + if (attrs.value("name") == QStringLiteral("ScintillaPrimaryView")) { + if (attrs.value("indentGuideLine") == QStringLiteral("show")) { + editor->setIndentationGuides(SC_IV_LOOKBOTH); + } + if (attrs.value("currentLineHilitingShow") == QStringLiteral("show")) { + editor->setCaretLineVisible(true); + editor->setCaretLineVisibleAlways(true); + } + if (attrs.value("Wrap") == QStringLiteral("yes")) { + editor->setWrapMode(SC_WRAP_WHITESPACE); + } + if (attrs.value("edge") == QStringLiteral("line")) { + editor->setEdgeMode(EDGE_LINE); + editor->setEdgeColumn(attrs.value("edgeNbColumn").toInt()); + } + if (attrs.value("whiteSpaceShow") == QStringLiteral("show")) { + editor->setViewWS(SCWS_VISIBLEALWAYS); + } + if (attrs.value("eolShow") == QStringLiteral("show")) { + editor->setViewEOL(true); + } + if (attrs.hasAttribute("folderMarkStyle")) { + editor->setAutomaticFold(SC_AUTOMATICFOLD_SHOW | SC_AUTOMATICFOLD_CLICK | SC_AUTOMATICFOLD_CHANGE); + editor->markerEnableHighlight(true); + const auto markers = folderMarkers[attrs.value("folderMarkStyle").toString()]; + const auto types = folderMarkers["type"]; + for (int i = 0; i < types.size(); ++i) { + editor->markerDefine(types[i], markers[i]); + editor->markerSetFore(types[i], foldFgColor); + editor->markerSetBack(types[i], foldBgColor); + editor->markerSetBackSelected(types[i], activeFgColor); + } + } + } + xml.skipCurrentElement(); + } +} diff --git a/src/NotepadNext/NppImporter.h b/src/NotepadNext/NppImporter.h new file mode 100644 index 000000000..52ca0cb83 --- /dev/null +++ b/src/NotepadNext/NppImporter.h @@ -0,0 +1,77 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef NPPIMPORTER_H +#define NPPIMPORTER_H + +#include +#include + +#include "ScintillaEdit.h" + +struct LexerStyle { + int id; + int fgColor; + int bgColor; + QString fontName; + int fontStyle; + int fontSize; + int keywordClass; +}; + +struct LexerType { + QString description; + QVector styles; +}; + +struct Language { + QString name; + QString shortName; + QString longDescription; + int lexer_id; + QStringList extensions; + LexerType lexer; + QMap keywords; +}; + +class NppImporter +{ +public: + NppImporter(const QString &configPath, ScintillaEdit *_editor); + + QMap languages; + QStringList sortedLanguageKeys; + +private: + ScintillaEdit *editor; + + void readLangsModel(const QString &filePath); + void readStylersModel(const QString &filePath); + void readConfigModel(const QString &filePath); + + void readLexerStyles(QXmlStreamReader &xml); + void readGlobalStyles(QXmlStreamReader &xml); + void readGUIConfigs(QXmlStreamReader &xml); + + int foldFgColor; + int foldBgColor; + int activeFgColor; +}; + +#endif // NPPIMPORTER_H diff --git a/src/NotepadNext/QRegexSearch.cpp b/src/NotepadNext/QRegexSearch.cpp new file mode 100644 index 000000000..74fe8374d --- /dev/null +++ b/src/NotepadNext/QRegexSearch.cpp @@ -0,0 +1,124 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "QRegexSearch.h" + +#include +#include + +using namespace Scintilla; + +#ifdef SCI_OWNREGEX +RegexSearchBase *Scintilla::Internal::CreateRegexSearch(CharClassify *charClassTable) +{ + Q_UNUSED(charClassTable); + + qInfo(Q_FUNC_INFO); + + return new QRegexSearch(); +} +#endif + +QRegexSearch::QRegexSearch() +{ + +} + +Sci::Position QRegexSearch::FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s, bool caseSensitive, bool word, bool wordStart, Scintilla::FindOption flags, Sci::Position *length) +{ + // ----------------------------------------------------------------------------------------------------------------------- + // NOTE: This section of code has to be very careful about what units of measure is being used. Scintilla wants to operate + // in units of bytes (e.g. position 3 is 3 bytes into the text). Qt wants to operate in units of UTF16 chars. The trouble is + // when you start using characters that are >1 byte a piece. Meaning position 3 (3 bytes into a file) could be 1 character. + // ----------------------------------------------------------------------------------------------------------------------- + + // Make sure the positiosn are outside of characters + minPos = doc->MovePositionOutsideChar(minPos, 1, false); + maxPos = doc->MovePositionOutsideChar(maxPos, -1, false); + + //qInfo(Q_FUNC_INFO); + //qInfo("\tminPos %d", minPos); + //qInfo("\tmaxPos %d", maxPos); + //qInfo("\ts %s", s); + //qInfo("\tcaseSensitive %s", caseSensitive ? "true" : "false"); + //qInfo("\tword %s", word ? "true" : "false"); + //qInfo("\twordStart %s", wordStart ? "true" : "false"); + //qInfo("\tflags %d", flags); + + // No need to search an empty range + if (minPos == maxPos) + return -1; + + auto options = QRegularExpression::MultilineOption | QRegularExpression::UseUnicodePropertiesOption; + + if (!FlagSet(flags, FindOption::MatchCase)) + options |= QRegularExpression::CaseInsensitiveOption; + + // TODO: does (*ANYCRLF) need prepended to the search string? + QRegularExpression re(s, options); + if (!re.isValid()) + return -1; // Invalid regular expression + + // Get the bytes from the document. No need to go past maxPos bytes + // Not actually sure if this copies the data or not + const Sci::Position rangeLength = maxPos - minPos; + const QString utf8 = QString::fromUtf8(doc->RangePointer(minPos, rangeLength), rangeLength); + + // NOTE: QString uses UTF16 counts since QChars are 16 bits + QRegularExpressionMatch m = re.match(utf8, 0, QRegularExpression::NormalMatch, QRegularExpression::NoMatchOption); + + if (!m.hasMatch()) + return -1; // No match + + match = m; + + // NOTE: Returned started is the index into the QString which uses UTF16 + const int positionStart = doc->GetRelativePositionUTF16(minPos, match.capturedStart(0)); + + // Now move ahead however many characters we matched. Again, based on UTF16 count + const int positionEnd = doc->GetRelativePositionUTF16(positionStart, match.capturedLength(0)); + + // The length is the number of bytes that was matched + *length = positionEnd - positionStart; + + return positionStart; +} + +const char *QRegexSearch::SubstituteByPosition(Document *doc, const char *text, Sci::Position *length) +{ + Q_UNUSED(doc); + + qInfo(Q_FUNC_INFO); + + Q_ASSERT(match.isValid()); + Q_ASSERT(match.hasMatch()); + + // Get the captured text and replace the match + QString newString = match.captured(); + newString.replace(match.regularExpression(), QByteArray(text, *length)); + + // TODO: figure out why this has to be new'd and can't be an instantiated class member + if (substituted) { + delete substituted; + } + + substituted = new QByteArray(newString.toUtf8()); + *length = substituted->length(); + return substituted->data(); +} diff --git a/src/NotepadNext/QRegexSearch.h b/src/NotepadNext/QRegexSearch.h new file mode 100644 index 000000000..9a44af559 --- /dev/null +++ b/src/NotepadNext/QRegexSearch.h @@ -0,0 +1,101 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef QREGEXSEARCH_H +#define QREGEXSEARCH_H + +#include + +#include +#include +#include +#include + + +// TODO: Fix this mess. Scintilla makes you include everything...in the correct order... +// this was copied from Editor.cxx just to get it to compile + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ScintillaTypes.h" +#include "ScintillaMessages.h" +#include "ScintillaStructures.h" +#include "ILoader.h" +#include "ILexer.h" + +#include "Debugging.h" +#include "Geometry.h" +#include "Platform.h" + +#include "CharacterType.h" +#include "CharacterCategoryMap.h" +#include "Position.h" +#include "UniqueString.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "ContractionState.h" +#include "CellBuffer.h" +#include "PerLine.h" +#include "KeyMap.h" +#include "Indicator.h" +#include "LineMarker.h" +#include "Style.h" +#include "ViewStyle.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "CaseFolder.h" +#include "Document.h" +#include "Scintilla.h" + +using namespace Scintilla::Internal; + +class QRegexSearch : public RegexSearchBase +{ +public: + QRegexSearch(); + + Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s, bool caseSensitive, bool word, bool wordStart, Scintilla::FindOption flags, Sci::Position *length) override; + const char *SubstituteByPosition(Document *doc, const char *text, Sci::Position *length) override; + +private: + QRegularExpressionMatch match; + QByteArray *substituted = Q_NULLPTR; +}; + +#endif // QREGEXSEARCH_H diff --git a/src/NotepadNext/QuickFindWidget.cpp b/src/NotepadNext/QuickFindWidget.cpp new file mode 100644 index 000000000..22408a1dd --- /dev/null +++ b/src/NotepadNext/QuickFindWidget.cpp @@ -0,0 +1,335 @@ +/* + * This file is part of Notepad Next. + * Copyright 2020 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "FocusWatcher.h" +#include "QuickFindWidget.h" +#include "ScintillaNext.h" +#include "FadingIndicator.h" +#include "ui_QuickFindWidget.h" + +#include +#include +#include +#include + +QuickFindWidget::QuickFindWidget(QWidget *parent) : + QFrame(parent), + ui(new Ui::QuickFindWidget) +{ + ui->setupUi(this); + + // Move the focus to the line edit widget + setFocusProxy(ui->lineEdit); + + ui->lineEdit->installEventFilter(this); + + FocusWatcher *fw = new FocusWatcher(ui->lineEdit); + connect(fw, &FocusWatcher::focusOut, this, &QuickFindWidget::focusOut); + connect(fw, &FocusWatcher::focusIn, this, &QuickFindWidget::focusIn); + + connect(ui->lineEdit, &QLineEdit::returnPressed, this, &QuickFindWidget::returnPressed); + + // Any changes need to trigger a new search + connect(ui->lineEdit, &QLineEdit::textChanged, this, &QuickFindWidget::performNewSearch); + connect(ui->buttonMatchCase, &QToolButton::toggled, this, &QuickFindWidget::performNewSearch); + connect(ui->buttonWholeWord, &QToolButton::toggled, this, &QuickFindWidget::performNewSearch); + connect(ui->buttonRegexp, &QToolButton::toggled, this, &QuickFindWidget::performNewSearch); +} + +QuickFindWidget::~QuickFindWidget() +{ + if (finder) { + delete finder; + } + + delete ui; +} + +void QuickFindWidget::setEditor(ScintillaNext *editor) +{ + if (this->editor != Q_NULLPTR) { + disconnect(editor, &ScintillaNext::resized, this, &QuickFindWidget::positionWidget); + } + + connect(editor, &ScintillaNext::resized, this, &QuickFindWidget::positionWidget); + + this->editor = editor; + + if (finder == Q_NULLPTR) { + finder = new Finder(editor); + finder->setWrap(true); // Always wrap the search + } + else { + finder->setEditor(editor); + } + + initializeEditorIndicator(); + + positionWidget(); +} + +bool QuickFindWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + + // Use escape key to close the quick find widget + if (keyEvent->key() == Qt::Key_Escape) { + clearHighlights(); + clearCachedMatches(); + hide(); + editor->grabFocus(); + } + } + + return QObject::eventFilter(obj, event); +} + +void QuickFindWidget::setSearchContextColorBad() +{ + setSearchContextColor(QStringLiteral("red")); +} + +void QuickFindWidget::setSearchContextColorGood() +{ + setSearchContextColor(QStringLiteral("blue")); +} + +void QuickFindWidget::performNewSearch() +{ + clearHighlights(); + clearCachedMatches(); + ui->lblInfo->hide(); + + // Early out + if (searchText().isEmpty()) { + setSearchContextColorGood(); + return; + } + + prepareSearch(); + finder->forEachMatch([&](int start, int end) { + matches.append(qMakePair(start, end)); + return qMax(start + 1, end); + }); + + if (matches.empty()) { + setSearchContextColorBad(); + } + else { + setSearchContextColorGood(); + } + + highlightMatches(); + navigateToNextMatch(false); +} + +void QuickFindWidget::highlightMatches() +{ + qInfo(Q_FUNC_INFO); + + editor->setIndicatorCurrent(indicator); + for (const auto &range : matches) { + editor->indicatorFillRange(range.first, range.second - range.first); + } +} + +void QuickFindWidget::showWrapIndicator() +{ + FadingIndicator::showPixmap(editor, QStringLiteral(":/icons/wrapindicator.png")); +} + +void QuickFindWidget::navigateToNextMatch(bool skipCurrent) +{ + qInfo(Q_FUNC_INFO); + + // Early out if there are no matches + if (matches.length() == 0) { + ui->lblInfo->hide(); + return; + } + + if (currentMatchIndex != -1) { + currentMatchIndex++; + if (currentMatchIndex >= matches.length()) { + currentMatchIndex = 0; + } + } + else { + int startPos = INVALID_POSITION; + if (skipCurrent) { + startPos = editor->selectionEnd(); + } + else { + startPos = editor->selectionStart(); + } + + auto it = std::lower_bound(matches.begin(), matches.end(), startPos, [](const QPair& pair, int value) { + return pair.first < value; + }); + + if (it != matches.end()) { + currentMatchIndex = std::distance(matches.begin(), it); + } else { + // Wrap back around + currentMatchIndex = 0; + } + } + + // Search wrapped around + if (currentMatchIndex == 0) { + showWrapIndicator(); + } + + goToCurrentMatch(); +} + +void QuickFindWidget::navigateToPrevMatch() +{ + qInfo(Q_FUNC_INFO); + + // Early out if there are no matches + if (matches.length() == 0) { + ui->lblInfo->hide(); + return; + } + + if (currentMatchIndex != -1) { + currentMatchIndex--; + if (currentMatchIndex < 0) { + currentMatchIndex = matches.length() - 1; + } + } + else { + qWarning("navigateToPrevMatch() with no valid index yet"); + return; + } + + // Search wrapped around + if (currentMatchIndex == matches.length() - 1) { + showWrapIndicator(); + } + + goToCurrentMatch(); +} + +void QuickFindWidget::goToCurrentMatch() +{ + editor->setSel(matches[currentMatchIndex].first, matches[currentMatchIndex].second); + editor->verticalCentreCaret(); + + ui->lblInfo->show(); + ui->lblInfo->setText(tr("%L1/%L2").arg(currentMatchIndex + 1).arg(matches.length())); +} + +int QuickFindWidget::computeSearchFlags() const +{ + int searchFlags = 0; + + if (ui->buttonMatchCase->isChecked()) { + searchFlags |= SCFIND_MATCHCASE; + } + + if (ui->buttonWholeWord->isChecked()) { + searchFlags |= SCFIND_WHOLEWORD; + } + + if (ui->buttonRegexp->isChecked()) { + searchFlags |= SCFIND_REGEXP; + } + + return searchFlags; +} + +void QuickFindWidget::setSearchContextColor(const QString &color) +{ + ui->lineEdit->setStyleSheet(QStringLiteral("border: 1px solid %1; padding: 2px;").arg(color)); +} + +void QuickFindWidget::initializeEditorIndicator() +{ + indicator = editor->allocateIndicator(QStringLiteral("quick_find")); + + editor->indicSetFore(indicator, 0xFF8000); + editor->indicSetStyle(indicator, INDIC_FULLBOX); + editor->indicSetOutlineAlpha(indicator, 150); + editor->indicSetAlpha(indicator, 50); + editor->indicSetUnder(indicator, true); +} + +QString QuickFindWidget::searchText() const +{ + return ui->lineEdit->text(); +} + +void QuickFindWidget::positionWidget() +{ + int usableWidth = editor->width(); + + // Account for the scrollbar as the quick find will be underneath if the scrollbar is visible + if (editor->verticalScrollBar() && editor->verticalScrollBar()->isVisible()) { + usableWidth -= editor->verticalScrollBar()->width(); + } + + QPoint position = QPoint(usableWidth - width(), 0); + + move(editor->mapTo(parentWidget(), position)); +} + +void QuickFindWidget::prepareSearch() +{ + finder->setSearchText(searchText()); + finder->setSearchFlags(computeSearchFlags()); +} + +void QuickFindWidget::focusIn() +{ + ui->lineEdit->selectAll(); + ui->lblInfo->hide(); + performNewSearch(); +} + +void QuickFindWidget::focusOut() +{ + clearHighlights(); + clearCachedMatches(); + hide(); +} + +void QuickFindWidget::returnPressed() +{ + if (QGuiApplication::keyboardModifiers() & Qt::ShiftModifier) { + navigateToPrevMatch(); + } + else { + navigateToNextMatch(true); + } +} + +void QuickFindWidget::clearHighlights() +{ + editor->setIndicatorCurrent(indicator); + editor->indicatorClearRange(0, editor->length()); +} + +void QuickFindWidget::clearCachedMatches() +{ + matches.clear(); + currentMatchIndex = -1; +} diff --git a/src/NotepadNext/QuickFindWidget.h b/src/NotepadNext/QuickFindWidget.h new file mode 100644 index 000000000..a92157b7b --- /dev/null +++ b/src/NotepadNext/QuickFindWidget.h @@ -0,0 +1,88 @@ +/* + * This file is part of Notepad Next. + * Copyright 2020 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef QUICKFINDWIDGET_H +#define QUICKFINDWIDGET_H + +#include +#include +#include +#include +#include + +#include "Finder.h" +#include "ScintillaNext.h" + +namespace Ui { +class QuickFindWidget; +} + + +class QuickFindWidget : public QFrame +{ + Q_OBJECT + +public: + explicit QuickFindWidget(QWidget *parent = nullptr); + ~QuickFindWidget(); + + void setEditor(ScintillaNext *editor); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +private slots: + void performNewSearch(); + void navigateToNextMatch(bool skipCurrent = true); + void navigateToPrevMatch(); + + void positionWidget(); + + void focusIn(); + void focusOut(); + + void returnPressed(); + +private: + void highlightMatches(); + void clearHighlights(); + void clearCachedMatches(); + + void prepareSearch(); + int computeSearchFlags() const; + + void setSearchContextColorBad(); + void setSearchContextColorGood(); + void setSearchContextColor(const QString &color); + + void initializeEditorIndicator(); + QString searchText() const; + void goToCurrentMatch(); + void showWrapIndicator(); + + Ui::QuickFindWidget *ui; + ScintillaNext *editor = Q_NULLPTR; + Finder *finder = Q_NULLPTR; + int indicator; + + QList> matches; + qsizetype currentMatchIndex = -1; +}; + +#endif // QUICKFINDWIDGET_H diff --git a/src/NotepadNext/QuickFindWidget.ui b/src/NotepadNext/QuickFindWidget.ui new file mode 100644 index 000000000..ace19f94a --- /dev/null +++ b/src/NotepadNext/QuickFindWidget.ui @@ -0,0 +1,118 @@ + + + QuickFindWidget + + + + 0 + 0 + 294 + 67 + + + + Qt::ClickFocus + + + Frame + + + true + + + + 6 + + + 6 + + + + + Find... + + + true + + + + + + + + + Match case + + + Aa + + + true + + + + + + + Match whole word + + + |A| + + + true + + + + + + + Use regular expression + + + . * + + + Alt+E + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QFrame::NoFrame + + + Placeholder + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + + + + diff --git a/src/NotepadNext/RangeAllocator.cpp b/src/NotepadNext/RangeAllocator.cpp new file mode 100644 index 000000000..e83ed70e1 --- /dev/null +++ b/src/NotepadNext/RangeAllocator.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "RangeAllocator.h" + +RangeAllocator::RangeAllocator(int total) : + resource(total) +{ +} + +void RangeAllocator::disableRange(int start, int end) +{ + resource.fill(true, start, end + 1); +} + +int RangeAllocator::requestResource(const QString name) +{ + // Check to see if this key is allocated yet + if (allocation.contains(name)) { + return allocation[name]; + } + + for (int i = 0; i < resource.size(); ++i) { + if (resource[i] == false) { + resource[i] = true; + allocation[name] = i; + return i; + } + } + + Q_ASSERT(false); + return -1; +} + diff --git a/src/NotepadNext/RangeAllocator.h b/src/NotepadNext/RangeAllocator.h new file mode 100644 index 000000000..1f0aa372c --- /dev/null +++ b/src/NotepadNext/RangeAllocator.h @@ -0,0 +1,39 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + +#include +#include + + +class RangeAllocator +{ +public: + explicit RangeAllocator(int total); + + void disableRange(int start, int end); + + int requestResource(const QString name); + +private: + QBitArray resource; + QMap allocation; +}; + diff --git a/src/NotepadNext/RecentFilesListManager.cpp b/src/NotepadNext/RecentFilesListManager.cpp new file mode 100644 index 000000000..29759224d --- /dev/null +++ b/src/NotepadNext/RecentFilesListManager.cpp @@ -0,0 +1,69 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "RecentFilesListManager.h" + +RecentFilesListManager::RecentFilesListManager(QObject *parent) : + QObject(parent) +{ +} + +void RecentFilesListManager::addFile(const QString &filePath) +{ + qInfo(Q_FUNC_INFO); + + // Attempt to remove it first to make sure it is not added twice + removeFile(filePath); + + // Set a limit on how many can be in the list + if (recentFiles.size() >= 10) { + recentFiles.removeLast(); + } + + recentFiles.prepend(filePath); +} + +void RecentFilesListManager::removeFile(const QString &filePath) +{ + recentFiles.removeOne(filePath); +} + +void RecentFilesListManager::clear() +{ + // Clear the file list + recentFiles.clear(); +} + +QString RecentFilesListManager::mostRecentFile() const +{ + Q_ASSERT(!recentFiles.empty()); + + return recentFiles.first(); +} + +QStringList RecentFilesListManager::fileList() const +{ + return recentFiles; +} + +void RecentFilesListManager::setFileList(const QStringList &list) +{ + clear(); + recentFiles.append(list); +} diff --git a/src/NotepadNext/RecentFilesListManager.h b/src/NotepadNext/RecentFilesListManager.h new file mode 100644 index 000000000..74a40a1d7 --- /dev/null +++ b/src/NotepadNext/RecentFilesListManager.h @@ -0,0 +1,48 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef RECENTFILESLISTMANAGER_H +#define RECENTFILESLISTMANAGER_H + +#include +#include + +class RecentFilesListManager : public QObject +{ + Q_OBJECT + +public: + explicit RecentFilesListManager(QObject *parent = Q_NULLPTR); + + QString mostRecentFile() const; + QStringList fileList() const; + void setFileList(const QStringList &list); + + int count() const { return recentFiles.size(); } + +public slots: + void addFile(const QString &filePath); + void removeFile(const QString &filePath); + void clear(); + +private: + QStringList recentFiles; +}; + +#endif // RECENTFILESLISTMANAGER_H diff --git a/src/NotepadNext/RecentFilesListMenuBuilder.cpp b/src/NotepadNext/RecentFilesListMenuBuilder.cpp new file mode 100644 index 000000000..a5a2d97ab --- /dev/null +++ b/src/NotepadNext/RecentFilesListMenuBuilder.cpp @@ -0,0 +1,56 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "RecentFilesListMenuBuilder.h" + +#include +#include +#include + +RecentFilesListMenuBuilder::RecentFilesListMenuBuilder(RecentFilesListManager *manager) : + QObject(manager), + manager(manager) +{ +} + +void RecentFilesListMenuBuilder::populateMenu(QMenu *menu) +{ + int i = 0; + + QList recentFileListActions; + for (const QString &file : manager->fileList()) { + ++i; + QAction *action = new QAction(QString("%1%2: %3").arg(i < 10 ? "&" : "").arg(i).arg(QDir::toNativeSeparators(file)), menu); + + action->setData(file); + connect(action, &QAction::triggered, this, &RecentFilesListMenuBuilder::recentFileActionTriggered); + + recentFileListActions.append(action); + } + + menu->addActions(recentFileListActions); +} + +void RecentFilesListMenuBuilder::recentFileActionTriggered() +{ + qInfo(Q_FUNC_INFO); + + const QAction *action = qobject_cast(sender()); + emit fileOpenRequest(action->data().toString()); +} diff --git a/src/NotepadNext/RecentFilesListMenuBuilder.h b/src/NotepadNext/RecentFilesListMenuBuilder.h new file mode 100644 index 000000000..7112ae415 --- /dev/null +++ b/src/NotepadNext/RecentFilesListMenuBuilder.h @@ -0,0 +1,46 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef RECENTFILESLISTMENUBUILDER_H +#define RECENTFILESLISTMENUBUILDER_H + +#include "RecentFilesListManager.h" +#include + +class QMenu; + +class RecentFilesListMenuBuilder : public QObject +{ + Q_OBJECT + +public: + explicit RecentFilesListMenuBuilder(RecentFilesListManager *manager); + void populateMenu(QMenu *menu); + +signals: + void fileOpenRequest(const QString &filePath); + +private slots: + void recentFileActionTriggered(); + +private: + RecentFilesListManager *manager; +}; + +#endif // RECENTFILESLISTMENUBUILDER_H diff --git a/src/NotepadNext/RtfConverter.cpp b/src/NotepadNext/RtfConverter.cpp new file mode 100644 index 000000000..598ac81b5 --- /dev/null +++ b/src/NotepadNext/RtfConverter.cpp @@ -0,0 +1,115 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "RtfConverter.h" + +#include +#include + +static void AddCharEscaped(QTextStream &stream, int ch) +{ + switch (ch) { + case '\n': + stream << QByteArrayLiteral("\\par") << Qt::endl; + break; + case '{': + stream << QByteArrayLiteral("\\{"); + break; + case '}': + stream << QByteArrayLiteral("\\}"); + break; + case '\t': + stream << QByteArrayLiteral("\\tab "); + break; + default: + stream << static_cast(ch); + } +} + +static QColor ScintillaColorToQColor(int color) +{ + int r = color & 0xFF; + int g = (color >> 8) & 0xFF; + int b = (color >> 16) & 0xFF; + + return QColor::fromRgb(r, g, b); +} + +void RtfConverter::convertRange(QTextStream &stream, int start, int end) +{ + ensureDocumentStyled(start, end); + + QByteArray rtf_body; + QTextStream rtf_stream(&rtf_body); + QVector styleColors; + int prevStyle = -1; + + for (int i = start; i < end; ++i) { + const int newStyle = editor->styleAt(i); + + if (newStyle != prevStyle) { + const QColor c = ScintillaColorToQColor(editor->styleFore(newStyle)); + + if (!styleColors.contains(c)) { + styleColors.append(c); + } + + // Turn bold off or non + if (prevStyle != -1 && editor->styleBold(prevStyle) && !editor->styleBold(newStyle)) { + rtf_stream << "\\b0"; + } + else if (editor->styleBold(newStyle)) { + rtf_stream << "\\b"; + } + + // Set the foreground color + rtf_stream << "\\cf" << styleColors.indexOf(c) << ' '; + + prevStyle = newStyle; + } + + // Output the character + const int ch = editor->charAt(i); + if (ch == '\r'){ + if (editor->charAt(i + 1) != '\n') { + AddCharEscaped(rtf_stream, ch); + } + } + else { + AddCharEscaped(rtf_stream, ch); + } + } + rtf_stream.flush(); + + stream << R"({\rtf1\ansi\deff0\deftab480)" << Qt::endl; + stream << R"({\fonttbl)" << Qt::endl; + stream << R"({\f0 )" << editor->styleFont(STYLE_DEFAULT) << ";}" << Qt::endl; + stream << R"(})" << Qt::endl; + stream << Qt::endl; + stream << R"({\colortbl)" << Qt::endl; + for (const auto &c : styleColors) { + stream << "\\red" << c.red() <<"\\green" << c.green() << "\\blue" << c.blue() << ";" << Qt::endl; + } + stream << R"(})" << Qt::endl; + stream << Qt::endl; + stream << "{" << Qt::endl; + stream << rtf_body << Qt::endl; + stream << "}" << Qt::endl; + stream.flush(); +} diff --git a/src/NotepadNext/RtfConverter.h b/src/NotepadNext/RtfConverter.h new file mode 100644 index 000000000..0dd141aee --- /dev/null +++ b/src/NotepadNext/RtfConverter.h @@ -0,0 +1,31 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + +#include "Converter.h" + +class RtfConverter : public Converter +{ + using Converter::Converter; + +public: + void convertRange(QTextStream &stream, int start, int end) override; +}; + diff --git a/src/NotepadNext/SciIFaceTable.cpp b/src/NotepadNext/SciIFaceTable.cpp new file mode 100644 index 000000000..88ba4238e --- /dev/null +++ b/src/NotepadNext/SciIFaceTable.cpp @@ -0,0 +1,3196 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "SciIFaceTable.h" + +//++Autogenerated -- start of section automatically generated from Scintilla.iface +static std::vector ifaceConstants = { + { "ANNOTATION_BOXED", 2 }, + { "ANNOTATION_HIDDEN", 0 }, + { "ANNOTATION_INDENTED", 3 }, + { "ANNOTATION_STANDARD", 1 }, + { "CARETSTYLE_BLOCK", 2 }, + { "CARETSTYLE_INVISIBLE", 0 }, + { "CARETSTYLE_LINE", 1 }, + { "CARETSTYLE_OVERSTRIKE_BAR", 0 }, + { "CARETSTYLE_OVERSTRIKE_BLOCK", 16 }, + { "CARET_EVEN", 0x08 }, + { "CARET_JUMPS", 0x10 }, + { "CARET_SLOP", 0x01 }, + { "CARET_STRICT", 0x04 }, + { "EDGE_BACKGROUND", 2 }, + { "EDGE_LINE", 1 }, + { "EDGE_MULTILINE", 3 }, + { "EDGE_NONE", 0 }, + { "INDIC0_MASK", 0x20 }, + { "INDIC1_MASK", 0x40 }, + { "INDIC2_MASK", 0x80 }, + { "INDICS_MASK", 0xE0 }, + { "INDIC_BOX", 6 }, + { "INDIC_COMPOSITIONTHICK", 14 }, + { "INDIC_COMPOSITIONTHIN", 15 }, + { "INDIC_CONTAINER", 8 }, + { "INDIC_DASH", 9 }, + { "INDIC_DIAGONAL", 3 }, + { "INDIC_DOTBOX", 12 }, + { "INDIC_DOTS", 10 }, + { "INDIC_FULLBOX", 16 }, + { "INDIC_GRADIENT", 20 }, + { "INDIC_GRADIENTCENTRE", 21 }, + { "INDIC_HIDDEN", 5 }, + { "INDIC_IME", 32 }, + { "INDIC_IME_MAX", 35 }, + { "INDIC_MAX", 35 }, + { "INDIC_PLAIN", 0 }, + { "INDIC_POINT", 18 }, + { "INDIC_POINTCHARACTER", 19 }, + { "INDIC_ROUNDBOX", 7 }, + { "INDIC_SQUIGGLE", 1 }, + { "INDIC_SQUIGGLELOW", 11 }, + { "INDIC_SQUIGGLEPIXMAP", 13 }, + { "INDIC_STRAIGHTBOX", 8 }, + { "INDIC_STRIKE", 4 }, + { "INDIC_TEXTFORE", 17 }, + { "INDIC_TT", 2 }, + { "INVALID_POSITION", -1 }, + { "KEYWORDSET_MAX", 8 }, + { "MARKER_MAX", 31 }, + { "SCEN_CHANGE", 768 }, + { "SCEN_KILLFOCUS", 256 }, + { "SCEN_SETFOCUS", 512 }, + { "SCE_A68K_COMMENT", 1 }, + { "SCE_A68K_COMMENT_DOXYGEN", 18 }, + { "SCE_A68K_COMMENT_SPECIAL", 17 }, + { "SCE_A68K_COMMENT_WORD", 16 }, + { "SCE_A68K_CPUINSTRUCTION", 7 }, + { "SCE_A68K_DEFAULT", 0 }, + { "SCE_A68K_DIRECTIVE", 10 }, + { "SCE_A68K_EXTINSTRUCTION", 8 }, + { "SCE_A68K_IDENTIFIER", 14 }, + { "SCE_A68K_LABEL", 12 }, + { "SCE_A68K_MACRO_ARG", 11 }, + { "SCE_A68K_MACRO_DECLARATION", 15 }, + { "SCE_A68K_NUMBER_BIN", 3 }, + { "SCE_A68K_NUMBER_DEC", 2 }, + { "SCE_A68K_NUMBER_HEX", 4 }, + { "SCE_A68K_OPERATOR", 6 }, + { "SCE_A68K_REGISTER", 9 }, + { "SCE_A68K_STRING1", 5 }, + { "SCE_A68K_STRING2", 13 }, + { "SCE_ABAQUS_ARGUMENT", 11 }, + { "SCE_ABAQUS_COMMAND", 8 }, + { "SCE_ABAQUS_COMMENT", 1 }, + { "SCE_ABAQUS_COMMENTBLOCK", 2 }, + { "SCE_ABAQUS_DEFAULT", 0 }, + { "SCE_ABAQUS_FUNCTION", 12 }, + { "SCE_ABAQUS_NUMBER", 3 }, + { "SCE_ABAQUS_OPERATOR", 5 }, + { "SCE_ABAQUS_PROCESSOR", 7 }, + { "SCE_ABAQUS_SLASHCOMMAND", 9 }, + { "SCE_ABAQUS_STARCOMMAND", 10 }, + { "SCE_ABAQUS_STRING", 4 }, + { "SCE_ABAQUS_WORD", 6 }, + { "SCE_ABL_BLOCK", 8 }, + { "SCE_ABL_CHARACTER", 4 }, + { "SCE_ABL_COMMENT", 10 }, + { "SCE_ABL_DEFAULT", 0 }, + { "SCE_ABL_END", 9 }, + { "SCE_ABL_IDENTIFIER", 7 }, + { "SCE_ABL_LINECOMMENT", 12 }, + { "SCE_ABL_NUMBER", 1 }, + { "SCE_ABL_OPERATOR", 6 }, + { "SCE_ABL_PREPROCESSOR", 5 }, + { "SCE_ABL_STRING", 3 }, + { "SCE_ABL_TASKMARKER", 11 }, + { "SCE_ABL_WORD", 2 }, + { "SCE_ADA_CHARACTER", 5 }, + { "SCE_ADA_CHARACTEREOL", 6 }, + { "SCE_ADA_COMMENTLINE", 10 }, + { "SCE_ADA_DEFAULT", 0 }, + { "SCE_ADA_DELIMITER", 4 }, + { "SCE_ADA_IDENTIFIER", 2 }, + { "SCE_ADA_ILLEGAL", 11 }, + { "SCE_ADA_LABEL", 9 }, + { "SCE_ADA_NUMBER", 3 }, + { "SCE_ADA_STRING", 7 }, + { "SCE_ADA_STRINGEOL", 8 }, + { "SCE_ADA_WORD", 1 }, + { "SCE_APDL_ARGUMENT", 11 }, + { "SCE_APDL_COMMAND", 8 }, + { "SCE_APDL_COMMENT", 1 }, + { "SCE_APDL_COMMENTBLOCK", 2 }, + { "SCE_APDL_DEFAULT", 0 }, + { "SCE_APDL_FUNCTION", 12 }, + { "SCE_APDL_NUMBER", 3 }, + { "SCE_APDL_OPERATOR", 5 }, + { "SCE_APDL_PROCESSOR", 7 }, + { "SCE_APDL_SLASHCOMMAND", 9 }, + { "SCE_APDL_STARCOMMAND", 10 }, + { "SCE_APDL_STRING", 4 }, + { "SCE_APDL_WORD", 6 }, + { "SCE_ASM_CHARACTER", 12 }, + { "SCE_ASM_COMMENT", 1 }, + { "SCE_ASM_COMMENTBLOCK", 11 }, + { "SCE_ASM_COMMENTDIRECTIVE", 15 }, + { "SCE_ASM_CPUINSTRUCTION", 6 }, + { "SCE_ASM_DEFAULT", 0 }, + { "SCE_ASM_DIRECTIVE", 9 }, + { "SCE_ASM_DIRECTIVEOPERAND", 10 }, + { "SCE_ASM_EXTINSTRUCTION", 14 }, + { "SCE_ASM_IDENTIFIER", 5 }, + { "SCE_ASM_MATHINSTRUCTION", 7 }, + { "SCE_ASM_NUMBER", 2 }, + { "SCE_ASM_OPERATOR", 4 }, + { "SCE_ASM_REGISTER", 8 }, + { "SCE_ASM_STRING", 3 }, + { "SCE_ASM_STRINGEOL", 13 }, + { "SCE_ASN1_ATTRIBUTE", 7 }, + { "SCE_ASN1_COMMENT", 1 }, + { "SCE_ASN1_DEFAULT", 0 }, + { "SCE_ASN1_DESCRIPTOR", 8 }, + { "SCE_ASN1_IDENTIFIER", 2 }, + { "SCE_ASN1_KEYWORD", 6 }, + { "SCE_ASN1_OID", 4 }, + { "SCE_ASN1_OPERATOR", 10 }, + { "SCE_ASN1_SCALAR", 5 }, + { "SCE_ASN1_STRING", 3 }, + { "SCE_ASN1_TYPE", 9 }, + { "SCE_ASY_CHARACTER", 6 }, + { "SCE_ASY_COMMENT", 1 }, + { "SCE_ASY_COMMENTLINE", 2 }, + { "SCE_ASY_COMMENTLINEDOC", 10 }, + { "SCE_ASY_DEFAULT", 0 }, + { "SCE_ASY_IDENTIFIER", 8 }, + { "SCE_ASY_NUMBER", 3 }, + { "SCE_ASY_OPERATOR", 7 }, + { "SCE_ASY_STRING", 5 }, + { "SCE_ASY_STRINGEOL", 9 }, + { "SCE_ASY_WORD", 4 }, + { "SCE_ASY_WORD2", 11 }, + { "SCE_AU3_COMMENT", 1 }, + { "SCE_AU3_COMMENTBLOCK", 2 }, + { "SCE_AU3_COMOBJ", 14 }, + { "SCE_AU3_DEFAULT", 0 }, + { "SCE_AU3_EXPAND", 13 }, + { "SCE_AU3_FUNCTION", 4 }, + { "SCE_AU3_KEYWORD", 5 }, + { "SCE_AU3_MACRO", 6 }, + { "SCE_AU3_NUMBER", 3 }, + { "SCE_AU3_OPERATOR", 8 }, + { "SCE_AU3_PREPROCESSOR", 11 }, + { "SCE_AU3_SENT", 10 }, + { "SCE_AU3_SPECIAL", 12 }, + { "SCE_AU3_STRING", 7 }, + { "SCE_AU3_UDF", 15 }, + { "SCE_AU3_VARIABLE", 9 }, + { "SCE_AVE_COMMENT", 1 }, + { "SCE_AVE_DEFAULT", 0 }, + { "SCE_AVE_ENUM", 7 }, + { "SCE_AVE_IDENTIFIER", 9 }, + { "SCE_AVE_NUMBER", 2 }, + { "SCE_AVE_OPERATOR", 10 }, + { "SCE_AVE_STRING", 6 }, + { "SCE_AVE_STRINGEOL", 8 }, + { "SCE_AVE_WORD", 3 }, + { "SCE_AVE_WORD1", 11 }, + { "SCE_AVE_WORD2", 12 }, + { "SCE_AVE_WORD3", 13 }, + { "SCE_AVE_WORD4", 14 }, + { "SCE_AVE_WORD5", 15 }, + { "SCE_AVE_WORD6", 16 }, + { "SCE_AVS_CLIPPROP", 13 }, + { "SCE_AVS_COMMENTBLOCK", 1 }, + { "SCE_AVS_COMMENTBLOCKN", 2 }, + { "SCE_AVS_COMMENTLINE", 3 }, + { "SCE_AVS_DEFAULT", 0 }, + { "SCE_AVS_FILTER", 10 }, + { "SCE_AVS_FUNCTION", 12 }, + { "SCE_AVS_IDENTIFIER", 6 }, + { "SCE_AVS_KEYWORD", 9 }, + { "SCE_AVS_NUMBER", 4 }, + { "SCE_AVS_OPERATOR", 5 }, + { "SCE_AVS_PLUGIN", 11 }, + { "SCE_AVS_STRING", 7 }, + { "SCE_AVS_TRIPLESTRING", 8 }, + { "SCE_AVS_USERDFN", 14 }, + { "SCE_BAAN_COMMENT", 1 }, + { "SCE_BAAN_COMMENTDOC", 2 }, + { "SCE_BAAN_DEFAULT", 0 }, + { "SCE_BAAN_DEFINEDEF", 24 }, + { "SCE_BAAN_DOMDEF", 21 }, + { "SCE_BAAN_FUNCDEF", 22 }, + { "SCE_BAAN_FUNCTION", 20 }, + { "SCE_BAAN_IDENTIFIER", 8 }, + { "SCE_BAAN_NUMBER", 3 }, + { "SCE_BAAN_OBJECTDEF", 23 }, + { "SCE_BAAN_OPERATOR", 7 }, + { "SCE_BAAN_PREPROCESSOR", 6 }, + { "SCE_BAAN_STRING", 5 }, + { "SCE_BAAN_STRINGEOL", 9 }, + { "SCE_BAAN_TABLEDEF", 18 }, + { "SCE_BAAN_TABLESQL", 19 }, + { "SCE_BAAN_WORD", 4 }, + { "SCE_BAAN_WORD2", 10 }, + { "SCE_BAAN_WORD3", 11 }, + { "SCE_BAAN_WORD4", 12 }, + { "SCE_BAAN_WORD5", 13 }, + { "SCE_BAAN_WORD6", 14 }, + { "SCE_BAAN_WORD7", 15 }, + { "SCE_BAAN_WORD8", 16 }, + { "SCE_BAAN_WORD9", 17 }, + { "SCE_BAT_COMMAND", 5 }, + { "SCE_BAT_COMMENT", 1 }, + { "SCE_BAT_DEFAULT", 0 }, + { "SCE_BAT_HIDE", 4 }, + { "SCE_BAT_IDENTIFIER", 6 }, + { "SCE_BAT_LABEL", 3 }, + { "SCE_BAT_OPERATOR", 7 }, + { "SCE_BAT_WORD", 2 }, + { "SCE_BIBTEX_COMMENT", 6 }, + { "SCE_BIBTEX_DEFAULT", 0 }, + { "SCE_BIBTEX_ENTRY", 1 }, + { "SCE_BIBTEX_KEY", 3 }, + { "SCE_BIBTEX_PARAMETER", 4 }, + { "SCE_BIBTEX_UNKNOWN_ENTRY", 2 }, + { "SCE_BIBTEX_VALUE", 5 }, + { "SCE_B_ASM", 14 }, + { "SCE_B_BINNUMBER", 18 }, + { "SCE_B_COMMENT", 1 }, + { "SCE_B_COMMENTBLOCK", 19 }, + { "SCE_B_CONSTANT", 13 }, + { "SCE_B_DATE", 8 }, + { "SCE_B_DEFAULT", 0 }, + { "SCE_B_DOCBLOCK", 21 }, + { "SCE_B_DOCKEYWORD", 22 }, + { "SCE_B_DOCLINE", 20 }, + { "SCE_B_ERROR", 16 }, + { "SCE_B_HEXNUMBER", 17 }, + { "SCE_B_IDENTIFIER", 7 }, + { "SCE_B_KEYWORD", 3 }, + { "SCE_B_KEYWORD2", 10 }, + { "SCE_B_KEYWORD3", 11 }, + { "SCE_B_KEYWORD4", 12 }, + { "SCE_B_LABEL", 15 }, + { "SCE_B_NUMBER", 2 }, + { "SCE_B_OPERATOR", 6 }, + { "SCE_B_PREPROCESSOR", 5 }, + { "SCE_B_STRING", 4 }, + { "SCE_B_STRINGEOL", 9 }, + { "SCE_CAML_CHAR", 9 }, + { "SCE_CAML_COMMENT", 12 }, + { "SCE_CAML_COMMENT1", 13 }, + { "SCE_CAML_COMMENT2", 14 }, + { "SCE_CAML_COMMENT3", 15 }, + { "SCE_CAML_DEFAULT", 0 }, + { "SCE_CAML_IDENTIFIER", 1 }, + { "SCE_CAML_KEYWORD", 3 }, + { "SCE_CAML_KEYWORD2", 4 }, + { "SCE_CAML_KEYWORD3", 5 }, + { "SCE_CAML_LINENUM", 6 }, + { "SCE_CAML_NUMBER", 8 }, + { "SCE_CAML_OPERATOR", 7 }, + { "SCE_CAML_STRING", 11 }, + { "SCE_CAML_TAGNAME", 2 }, + { "SCE_CAML_WHITE", 10 }, + { "SCE_CIL_COMMENT", 1 }, + { "SCE_CIL_COMMENTLINE", 2 }, + { "SCE_CIL_DEFAULT", 0 }, + { "SCE_CIL_IDENTIFIER", 9 }, + { "SCE_CIL_LABEL", 7 }, + { "SCE_CIL_OPERATOR", 8 }, + { "SCE_CIL_STRING", 6 }, + { "SCE_CIL_STRINGEOL", 10 }, + { "SCE_CIL_WORD", 3 }, + { "SCE_CIL_WORD2", 4 }, + { "SCE_CIL_WORD3", 5 }, + { "SCE_CLW_ATTRIBUTE", 13 }, + { "SCE_CLW_BUILTIN_PROCEDURES_FUNCTION", 11 }, + { "SCE_CLW_COMMENT", 2 }, + { "SCE_CLW_COMPILER_DIRECTIVE", 9 }, + { "SCE_CLW_DEFAULT", 0 }, + { "SCE_CLW_DEPRECATED", 16 }, + { "SCE_CLW_ERROR", 15 }, + { "SCE_CLW_INTEGER_CONSTANT", 5 }, + { "SCE_CLW_KEYWORD", 8 }, + { "SCE_CLW_LABEL", 1 }, + { "SCE_CLW_PICTURE_STRING", 7 }, + { "SCE_CLW_REAL_CONSTANT", 6 }, + { "SCE_CLW_RUNTIME_EXPRESSIONS", 10 }, + { "SCE_CLW_STANDARD_EQUATE", 14 }, + { "SCE_CLW_STRING", 3 }, + { "SCE_CLW_STRUCTURE_DATA_TYPE", 12 }, + { "SCE_CLW_USER_IDENTIFIER", 4 }, + { "SCE_CMAKE_COMMANDS", 5 }, + { "SCE_CMAKE_COMMENT", 1 }, + { "SCE_CMAKE_DEFAULT", 0 }, + { "SCE_CMAKE_FOREACHDEF", 10 }, + { "SCE_CMAKE_IFDEFINEDEF", 11 }, + { "SCE_CMAKE_MACRODEF", 12 }, + { "SCE_CMAKE_NUMBER", 14 }, + { "SCE_CMAKE_PARAMETERS", 6 }, + { "SCE_CMAKE_STRINGDQ", 2 }, + { "SCE_CMAKE_STRINGLQ", 3 }, + { "SCE_CMAKE_STRINGRQ", 4 }, + { "SCE_CMAKE_STRINGVAR", 13 }, + { "SCE_CMAKE_USERDEFINED", 8 }, + { "SCE_CMAKE_VARIABLE", 7 }, + { "SCE_CMAKE_WHILEDEF", 9 }, + { "SCE_COFFEESCRIPT_CHARACTER", 7 }, + { "SCE_COFFEESCRIPT_COMMENT", 1 }, + { "SCE_COFFEESCRIPT_COMMENTBLOCK", 22 }, + { "SCE_COFFEESCRIPT_COMMENTDOC", 3 }, + { "SCE_COFFEESCRIPT_COMMENTDOCKEYWORD", 17 }, + { "SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR", 18 }, + { "SCE_COFFEESCRIPT_COMMENTLINE", 2 }, + { "SCE_COFFEESCRIPT_COMMENTLINEDOC", 15 }, + { "SCE_COFFEESCRIPT_DEFAULT", 0 }, + { "SCE_COFFEESCRIPT_GLOBALCLASS", 19 }, + { "SCE_COFFEESCRIPT_IDENTIFIER", 11 }, + { "SCE_COFFEESCRIPT_INSTANCEPROPERTY", 25 }, + { "SCE_COFFEESCRIPT_NUMBER", 4 }, + { "SCE_COFFEESCRIPT_OPERATOR", 10 }, + { "SCE_COFFEESCRIPT_PREPROCESSOR", 9 }, + { "SCE_COFFEESCRIPT_REGEX", 14 }, + { "SCE_COFFEESCRIPT_STRING", 6 }, + { "SCE_COFFEESCRIPT_STRINGEOL", 12 }, + { "SCE_COFFEESCRIPT_STRINGRAW", 20 }, + { "SCE_COFFEESCRIPT_TRIPLEVERBATIM", 21 }, + { "SCE_COFFEESCRIPT_UUID", 8 }, + { "SCE_COFFEESCRIPT_VERBATIM", 13 }, + { "SCE_COFFEESCRIPT_VERBOSE_REGEX", 23 }, + { "SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT", 24 }, + { "SCE_COFFEESCRIPT_WORD", 5 }, + { "SCE_COFFEESCRIPT_WORD2", 16 }, + { "SCE_CONF_COMMENT", 1 }, + { "SCE_CONF_DEFAULT", 0 }, + { "SCE_CONF_DIRECTIVE", 9 }, + { "SCE_CONF_EXTENSION", 4 }, + { "SCE_CONF_IDENTIFIER", 3 }, + { "SCE_CONF_IP", 8 }, + { "SCE_CONF_NUMBER", 2 }, + { "SCE_CONF_OPERATOR", 7 }, + { "SCE_CONF_PARAMETER", 5 }, + { "SCE_CONF_STRING", 6 }, + { "SCE_CSOUND_ARATE_VAR", 11 }, + { "SCE_CSOUND_COMMENT", 1 }, + { "SCE_CSOUND_COMMENTBLOCK", 9 }, + { "SCE_CSOUND_DEFAULT", 0 }, + { "SCE_CSOUND_GLOBAL_VAR", 14 }, + { "SCE_CSOUND_HEADERSTMT", 7 }, + { "SCE_CSOUND_IDENTIFIER", 5 }, + { "SCE_CSOUND_INSTR", 4 }, + { "SCE_CSOUND_IRATE_VAR", 13 }, + { "SCE_CSOUND_KRATE_VAR", 12 }, + { "SCE_CSOUND_NUMBER", 2 }, + { "SCE_CSOUND_OPCODE", 6 }, + { "SCE_CSOUND_OPERATOR", 3 }, + { "SCE_CSOUND_PARAM", 10 }, + { "SCE_CSOUND_STRINGEOL", 15 }, + { "SCE_CSOUND_USERKEYWORD", 8 }, + { "SCE_CSS_ATTRIBUTE", 16 }, + { "SCE_CSS_CLASS", 2 }, + { "SCE_CSS_COMMENT", 9 }, + { "SCE_CSS_DEFAULT", 0 }, + { "SCE_CSS_DIRECTIVE", 12 }, + { "SCE_CSS_DOUBLESTRING", 13 }, + { "SCE_CSS_EXTENDED_IDENTIFIER", 19 }, + { "SCE_CSS_EXTENDED_PSEUDOCLASS", 20 }, + { "SCE_CSS_EXTENDED_PSEUDOELEMENT", 21 }, + { "SCE_CSS_ID", 10 }, + { "SCE_CSS_IDENTIFIER", 6 }, + { "SCE_CSS_IDENTIFIER2", 15 }, + { "SCE_CSS_IDENTIFIER3", 17 }, + { "SCE_CSS_IMPORTANT", 11 }, + { "SCE_CSS_MEDIA", 22 }, + { "SCE_CSS_OPERATOR", 5 }, + { "SCE_CSS_PSEUDOCLASS", 3 }, + { "SCE_CSS_PSEUDOELEMENT", 18 }, + { "SCE_CSS_SINGLESTRING", 14 }, + { "SCE_CSS_TAG", 1 }, + { "SCE_CSS_UNKNOWN_IDENTIFIER", 7 }, + { "SCE_CSS_UNKNOWN_PSEUDOCLASS", 4 }, + { "SCE_CSS_VALUE", 8 }, + { "SCE_CSS_VARIABLE", 23 }, + { "SCE_C_CHARACTER", 7 }, + { "SCE_C_COMMENT", 1 }, + { "SCE_C_COMMENTDOC", 3 }, + { "SCE_C_COMMENTDOCKEYWORD", 17 }, + { "SCE_C_COMMENTDOCKEYWORDERROR", 18 }, + { "SCE_C_COMMENTLINE", 2 }, + { "SCE_C_COMMENTLINEDOC", 15 }, + { "SCE_C_DEFAULT", 0 }, + { "SCE_C_ESCAPESEQUENCE", 27 }, + { "SCE_C_GLOBALCLASS", 19 }, + { "SCE_C_HASHQUOTEDSTRING", 22 }, + { "SCE_C_IDENTIFIER", 11 }, + { "SCE_C_NUMBER", 4 }, + { "SCE_C_OPERATOR", 10 }, + { "SCE_C_PREPROCESSOR", 9 }, + { "SCE_C_PREPROCESSORCOMMENT", 23 }, + { "SCE_C_PREPROCESSORCOMMENTDOC", 24 }, + { "SCE_C_REGEX", 14 }, + { "SCE_C_STRING", 6 }, + { "SCE_C_STRINGEOL", 12 }, + { "SCE_C_STRINGRAW", 20 }, + { "SCE_C_TASKMARKER", 26 }, + { "SCE_C_TRIPLEVERBATIM", 21 }, + { "SCE_C_USERLITERAL", 25 }, + { "SCE_C_UUID", 8 }, + { "SCE_C_VERBATIM", 13 }, + { "SCE_C_WORD", 5 }, + { "SCE_C_WORD2", 16 }, + { "SCE_DIFF_ADDED", 6 }, + { "SCE_DIFF_CHANGED", 7 }, + { "SCE_DIFF_COMMAND", 2 }, + { "SCE_DIFF_COMMENT", 1 }, + { "SCE_DIFF_DEFAULT", 0 }, + { "SCE_DIFF_DELETED", 5 }, + { "SCE_DIFF_HEADER", 3 }, + { "SCE_DIFF_PATCH_ADD", 8 }, + { "SCE_DIFF_PATCH_DELETE", 9 }, + { "SCE_DIFF_POSITION", 4 }, + { "SCE_DIFF_REMOVED_PATCH_ADD", 10 }, + { "SCE_DIFF_REMOVED_PATCH_DELETE", 11 }, + { "SCE_DMAP_COMMENT", 1 }, + { "SCE_DMAP_DEFAULT", 0 }, + { "SCE_DMAP_IDENTIFIER", 7 }, + { "SCE_DMAP_NUMBER", 2 }, + { "SCE_DMAP_OPERATOR", 6 }, + { "SCE_DMAP_STRING1", 3 }, + { "SCE_DMAP_STRING2", 4 }, + { "SCE_DMAP_STRINGEOL", 5 }, + { "SCE_DMAP_WORD", 8 }, + { "SCE_DMAP_WORD2", 9 }, + { "SCE_DMAP_WORD3", 10 }, + { "SCE_DMIS_COMMENT", 1 }, + { "SCE_DMIS_DEFAULT", 0 }, + { "SCE_DMIS_KEYWORD", 4 }, + { "SCE_DMIS_LABEL", 9 }, + { "SCE_DMIS_MAJORWORD", 5 }, + { "SCE_DMIS_MINORWORD", 6 }, + { "SCE_DMIS_NUMBER", 3 }, + { "SCE_DMIS_STRING", 2 }, + { "SCE_DMIS_UNSUPPORTED_MAJOR", 7 }, + { "SCE_DMIS_UNSUPPORTED_MINOR", 8 }, + { "SCE_D_CHARACTER", 12 }, + { "SCE_D_COMMENT", 1 }, + { "SCE_D_COMMENTDOC", 3 }, + { "SCE_D_COMMENTDOCKEYWORD", 16 }, + { "SCE_D_COMMENTDOCKEYWORDERROR", 17 }, + { "SCE_D_COMMENTLINE", 2 }, + { "SCE_D_COMMENTLINEDOC", 15 }, + { "SCE_D_COMMENTNESTED", 4 }, + { "SCE_D_DEFAULT", 0 }, + { "SCE_D_IDENTIFIER", 14 }, + { "SCE_D_NUMBER", 5 }, + { "SCE_D_OPERATOR", 13 }, + { "SCE_D_STRING", 10 }, + { "SCE_D_STRINGB", 18 }, + { "SCE_D_STRINGEOL", 11 }, + { "SCE_D_STRINGR", 19 }, + { "SCE_D_TYPEDEF", 9 }, + { "SCE_D_WORD", 6 }, + { "SCE_D_WORD2", 7 }, + { "SCE_D_WORD3", 8 }, + { "SCE_D_WORD5", 20 }, + { "SCE_D_WORD6", 21 }, + { "SCE_D_WORD7", 22 }, + { "SCE_ECL_ADDED", 24 }, + { "SCE_ECL_CHANGED", 26 }, + { "SCE_ECL_CHARACTER", 7 }, + { "SCE_ECL_COMMENT", 1 }, + { "SCE_ECL_COMMENTDOC", 23 }, + { "SCE_ECL_COMMENTDOCKEYWORD", 17 }, + { "SCE_ECL_COMMENTDOCKEYWORDERROR", 18 }, + { "SCE_ECL_COMMENTLINE", 2 }, + { "SCE_ECL_COMMENTLINEDOC", 15 }, + { "SCE_ECL_DEFAULT", 0 }, + { "SCE_ECL_DELETED", 25 }, + { "SCE_ECL_IDENTIFIER", 11 }, + { "SCE_ECL_MOVED", 27 }, + { "SCE_ECL_NUMBER", 3 }, + { "SCE_ECL_OPERATOR", 6 }, + { "SCE_ECL_PREPROCESSOR", 9 }, + { "SCE_ECL_REGEX", 14 }, + { "SCE_ECL_STRING", 4 }, + { "SCE_ECL_STRINGEOL", 12 }, + { "SCE_ECL_UNKNOWN", 10 }, + { "SCE_ECL_UUID", 8 }, + { "SCE_ECL_VERBATIM", 13 }, + { "SCE_ECL_WORD0", 5 }, + { "SCE_ECL_WORD1", 16 }, + { "SCE_ECL_WORD2", 19 }, + { "SCE_ECL_WORD3", 20 }, + { "SCE_ECL_WORD4", 21 }, + { "SCE_ECL_WORD5", 22 }, + { "SCE_EDI_BADSEGMENT", 8 }, + { "SCE_EDI_DEFAULT", 0 }, + { "SCE_EDI_SEGMENTEND", 2 }, + { "SCE_EDI_SEGMENTSTART", 1 }, + { "SCE_EDI_SEP_COMPOSITE", 4 }, + { "SCE_EDI_SEP_ELEMENT", 3 }, + { "SCE_EDI_SEP_RELEASE", 5 }, + { "SCE_EDI_UNA", 6 }, + { "SCE_EDI_UNH", 7 }, + { "SCE_EIFFEL_CHARACTER", 5 }, + { "SCE_EIFFEL_COMMENTLINE", 1 }, + { "SCE_EIFFEL_DEFAULT", 0 }, + { "SCE_EIFFEL_IDENTIFIER", 7 }, + { "SCE_EIFFEL_NUMBER", 2 }, + { "SCE_EIFFEL_OPERATOR", 6 }, + { "SCE_EIFFEL_STRING", 4 }, + { "SCE_EIFFEL_STRINGEOL", 8 }, + { "SCE_EIFFEL_WORD", 3 }, + { "SCE_ERLANG_ATOM", 7 }, + { "SCE_ERLANG_ATOM_QUOTED", 18 }, + { "SCE_ERLANG_BIFS", 22 }, + { "SCE_ERLANG_CHARACTER", 9 }, + { "SCE_ERLANG_COMMENT", 1 }, + { "SCE_ERLANG_COMMENT_DOC", 16 }, + { "SCE_ERLANG_COMMENT_DOC_MACRO", 17 }, + { "SCE_ERLANG_COMMENT_FUNCTION", 14 }, + { "SCE_ERLANG_COMMENT_MODULE", 15 }, + { "SCE_ERLANG_DEFAULT", 0 }, + { "SCE_ERLANG_FUNCTION_NAME", 8 }, + { "SCE_ERLANG_KEYWORD", 4 }, + { "SCE_ERLANG_MACRO", 10 }, + { "SCE_ERLANG_MACRO_QUOTED", 19 }, + { "SCE_ERLANG_MODULES", 23 }, + { "SCE_ERLANG_MODULES_ATT", 24 }, + { "SCE_ERLANG_NODE_NAME", 13 }, + { "SCE_ERLANG_NODE_NAME_QUOTED", 21 }, + { "SCE_ERLANG_NUMBER", 3 }, + { "SCE_ERLANG_OPERATOR", 6 }, + { "SCE_ERLANG_PREPROC", 12 }, + { "SCE_ERLANG_RECORD", 11 }, + { "SCE_ERLANG_RECORD_QUOTED", 20 }, + { "SCE_ERLANG_STRING", 5 }, + { "SCE_ERLANG_UNKNOWN", 31 }, + { "SCE_ERLANG_VARIABLE", 2 }, + { "SCE_ERR_ABSF", 18 }, + { "SCE_ERR_BORLAND", 5 }, + { "SCE_ERR_CMD", 4 }, + { "SCE_ERR_CTAG", 9 }, + { "SCE_ERR_DEFAULT", 0 }, + { "SCE_ERR_DIFF_ADDITION", 11 }, + { "SCE_ERR_DIFF_CHANGED", 10 }, + { "SCE_ERR_DIFF_DELETION", 12 }, + { "SCE_ERR_DIFF_MESSAGE", 13 }, + { "SCE_ERR_ELF", 15 }, + { "SCE_ERR_ESCSEQ", 23 }, + { "SCE_ERR_ESCSEQ_UNKNOWN", 24 }, + { "SCE_ERR_ES_BLACK", 40 }, + { "SCE_ERR_ES_BLUE", 44 }, + { "SCE_ERR_ES_BRIGHT_BLUE", 52 }, + { "SCE_ERR_ES_BRIGHT_CYAN", 54 }, + { "SCE_ERR_ES_BRIGHT_GREEN", 50 }, + { "SCE_ERR_ES_BRIGHT_MAGENTA", 53 }, + { "SCE_ERR_ES_BRIGHT_RED", 49 }, + { "SCE_ERR_ES_BROWN", 43 }, + { "SCE_ERR_ES_CYAN", 46 }, + { "SCE_ERR_ES_DARK_GRAY", 48 }, + { "SCE_ERR_ES_GRAY", 47 }, + { "SCE_ERR_ES_GREEN", 42 }, + { "SCE_ERR_ES_MAGENTA", 45 }, + { "SCE_ERR_ES_RED", 41 }, + { "SCE_ERR_ES_WHITE", 55 }, + { "SCE_ERR_ES_YELLOW", 51 }, + { "SCE_ERR_GCC", 2 }, + { "SCE_ERR_GCC_INCLUDED_FROM", 22 }, + { "SCE_ERR_IFC", 16 }, + { "SCE_ERR_IFORT", 17 }, + { "SCE_ERR_JAVA_STACK", 20 }, + { "SCE_ERR_LUA", 8 }, + { "SCE_ERR_MS", 3 }, + { "SCE_ERR_NET", 7 }, + { "SCE_ERR_PERL", 6 }, + { "SCE_ERR_PHP", 14 }, + { "SCE_ERR_PYTHON", 1 }, + { "SCE_ERR_TIDY", 19 }, + { "SCE_ERR_VALUE", 21 }, + { "SCE_ESCRIPT_BRACE", 9 }, + { "SCE_ESCRIPT_COMMENT", 1 }, + { "SCE_ESCRIPT_COMMENTDOC", 3 }, + { "SCE_ESCRIPT_COMMENTLINE", 2 }, + { "SCE_ESCRIPT_DEFAULT", 0 }, + { "SCE_ESCRIPT_IDENTIFIER", 8 }, + { "SCE_ESCRIPT_NUMBER", 4 }, + { "SCE_ESCRIPT_OPERATOR", 7 }, + { "SCE_ESCRIPT_STRING", 6 }, + { "SCE_ESCRIPT_WORD", 5 }, + { "SCE_ESCRIPT_WORD2", 10 }, + { "SCE_ESCRIPT_WORD3", 11 }, + { "SCE_FORTH_COMMENT", 1 }, + { "SCE_FORTH_COMMENT_ML", 2 }, + { "SCE_FORTH_CONTROL", 4 }, + { "SCE_FORTH_DEFAULT", 0 }, + { "SCE_FORTH_DEFWORD", 6 }, + { "SCE_FORTH_IDENTIFIER", 3 }, + { "SCE_FORTH_KEYWORD", 5 }, + { "SCE_FORTH_LOCALE", 11 }, + { "SCE_FORTH_NUMBER", 9 }, + { "SCE_FORTH_PREWORD1", 7 }, + { "SCE_FORTH_PREWORD2", 8 }, + { "SCE_FORTH_STRING", 10 }, + { "SCE_FS_COMMENT", 1 }, + { "SCE_FS_COMMENTDOC", 3 }, + { "SCE_FS_COMMENTDOCKEYWORD", 5 }, + { "SCE_FS_COMMENTDOCKEYWORDERROR", 6 }, + { "SCE_FS_COMMENTDOC_C", 22 }, + { "SCE_FS_COMMENTLINE", 2 }, + { "SCE_FS_COMMENTLINEDOC", 4 }, + { "SCE_FS_COMMENTLINEDOC_C", 23 }, + { "SCE_FS_CONSTANT", 18 }, + { "SCE_FS_DATE", 16 }, + { "SCE_FS_DEFAULT", 0 }, + { "SCE_FS_DEFAULT_C", 21 }, + { "SCE_FS_DISABLEDCODE", 20 }, + { "SCE_FS_IDENTIFIER", 15 }, + { "SCE_FS_IDENTIFIER_C", 30 }, + { "SCE_FS_KEYWORD", 7 }, + { "SCE_FS_KEYWORD2", 8 }, + { "SCE_FS_KEYWORD2_C", 25 }, + { "SCE_FS_KEYWORD3", 9 }, + { "SCE_FS_KEYWORD4", 10 }, + { "SCE_FS_KEYWORD_C", 24 }, + { "SCE_FS_NUMBER", 11 }, + { "SCE_FS_NUMBER_C", 26 }, + { "SCE_FS_OPERATOR", 14 }, + { "SCE_FS_OPERATOR_C", 29 }, + { "SCE_FS_PREPROCESSOR", 13 }, + { "SCE_FS_PREPROCESSOR_C", 28 }, + { "SCE_FS_STRING", 12 }, + { "SCE_FS_STRINGEOL", 17 }, + { "SCE_FS_STRINGEOL_C", 31 }, + { "SCE_FS_STRING_C", 27 }, + { "SCE_FS_WORDOPERATOR", 19 }, + { "SCE_F_COMMENT", 1 }, + { "SCE_F_CONTINUATION", 14 }, + { "SCE_F_DEFAULT", 0 }, + { "SCE_F_IDENTIFIER", 7 }, + { "SCE_F_LABEL", 13 }, + { "SCE_F_NUMBER", 2 }, + { "SCE_F_OPERATOR", 6 }, + { "SCE_F_OPERATOR2", 12 }, + { "SCE_F_PREPROCESSOR", 11 }, + { "SCE_F_STRING1", 3 }, + { "SCE_F_STRING2", 4 }, + { "SCE_F_STRINGEOL", 5 }, + { "SCE_F_WORD", 8 }, + { "SCE_F_WORD2", 9 }, + { "SCE_F_WORD3", 10 }, + { "SCE_GAP_CHAR", 7 }, + { "SCE_GAP_COMMENT", 9 }, + { "SCE_GAP_DEFAULT", 0 }, + { "SCE_GAP_IDENTIFIER", 1 }, + { "SCE_GAP_KEYWORD", 2 }, + { "SCE_GAP_KEYWORD2", 3 }, + { "SCE_GAP_KEYWORD3", 4 }, + { "SCE_GAP_KEYWORD4", 5 }, + { "SCE_GAP_NUMBER", 10 }, + { "SCE_GAP_OPERATOR", 8 }, + { "SCE_GAP_STRING", 6 }, + { "SCE_GAP_STRINGEOL", 11 }, + { "SCE_GC_ATTRIBUTE", 5 }, + { "SCE_GC_COMMAND", 7 }, + { "SCE_GC_COMMENTBLOCK", 2 }, + { "SCE_GC_COMMENTLINE", 1 }, + { "SCE_GC_CONTROL", 6 }, + { "SCE_GC_DEFAULT", 0 }, + { "SCE_GC_EVENT", 4 }, + { "SCE_GC_GLOBAL", 3 }, + { "SCE_GC_OPERATOR", 9 }, + { "SCE_GC_STRING", 8 }, + { "SCE_HA_CAPITAL", 8 }, + { "SCE_HA_CHARACTER", 5 }, + { "SCE_HA_CLASS", 6 }, + { "SCE_HA_COMMENTBLOCK", 14 }, + { "SCE_HA_COMMENTBLOCK2", 15 }, + { "SCE_HA_COMMENTBLOCK3", 16 }, + { "SCE_HA_COMMENTLINE", 13 }, + { "SCE_HA_DATA", 9 }, + { "SCE_HA_DEFAULT", 0 }, + { "SCE_HA_IDENTIFIER", 1 }, + { "SCE_HA_IMPORT", 10 }, + { "SCE_HA_INSTANCE", 12 }, + { "SCE_HA_KEYWORD", 2 }, + { "SCE_HA_LITERATE_CODEDELIM", 22 }, + { "SCE_HA_LITERATE_COMMENT", 21 }, + { "SCE_HA_MODULE", 7 }, + { "SCE_HA_NUMBER", 3 }, + { "SCE_HA_OPERATOR", 11 }, + { "SCE_HA_PRAGMA", 17 }, + { "SCE_HA_PREPROCESSOR", 18 }, + { "SCE_HA_RESERVED_OPERATOR", 20 }, + { "SCE_HA_STRING", 4 }, + { "SCE_HA_STRINGEOL", 19 }, + { "SCE_HBA_COMMENTLINE", 82 }, + { "SCE_HBA_DEFAULT", 81 }, + { "SCE_HBA_IDENTIFIER", 86 }, + { "SCE_HBA_NUMBER", 83 }, + { "SCE_HBA_START", 80 }, + { "SCE_HBA_STRING", 85 }, + { "SCE_HBA_STRINGEOL", 87 }, + { "SCE_HBA_WORD", 84 }, + { "SCE_HB_COMMENTLINE", 72 }, + { "SCE_HB_DEFAULT", 71 }, + { "SCE_HB_IDENTIFIER", 76 }, + { "SCE_HB_NUMBER", 73 }, + { "SCE_HB_START", 70 }, + { "SCE_HB_STRING", 75 }, + { "SCE_HB_STRINGEOL", 77 }, + { "SCE_HB_WORD", 74 }, + { "SCE_HEX_ADDRESSFIELD_UNKNOWN", 10 }, + { "SCE_HEX_BYTECOUNT", 4 }, + { "SCE_HEX_BYTECOUNT_WRONG", 5 }, + { "SCE_HEX_CHECKSUM", 16 }, + { "SCE_HEX_CHECKSUM_WRONG", 17 }, + { "SCE_HEX_DATAADDRESS", 7 }, + { "SCE_HEX_DATA_EMPTY", 15 }, + { "SCE_HEX_DATA_EVEN", 13 }, + { "SCE_HEX_DATA_ODD", 12 }, + { "SCE_HEX_DATA_UNKNOWN", 14 }, + { "SCE_HEX_DEFAULT", 0 }, + { "SCE_HEX_EXTENDEDADDRESS", 11 }, + { "SCE_HEX_GARBAGE", 18 }, + { "SCE_HEX_NOADDRESS", 6 }, + { "SCE_HEX_RECCOUNT", 8 }, + { "SCE_HEX_RECSTART", 1 }, + { "SCE_HEX_RECTYPE", 2 }, + { "SCE_HEX_RECTYPE_UNKNOWN", 3 }, + { "SCE_HEX_STARTADDRESS", 9 }, + { "SCE_HJA_COMMENT", 57 }, + { "SCE_HJA_COMMENTDOC", 59 }, + { "SCE_HJA_COMMENTLINE", 58 }, + { "SCE_HJA_DEFAULT", 56 }, + { "SCE_HJA_DOUBLESTRING", 63 }, + { "SCE_HJA_KEYWORD", 62 }, + { "SCE_HJA_NUMBER", 60 }, + { "SCE_HJA_REGEX", 67 }, + { "SCE_HJA_SINGLESTRING", 64 }, + { "SCE_HJA_START", 55 }, + { "SCE_HJA_STRINGEOL", 66 }, + { "SCE_HJA_SYMBOLS", 65 }, + { "SCE_HJA_WORD", 61 }, + { "SCE_HJ_COMMENT", 42 }, + { "SCE_HJ_COMMENTDOC", 44 }, + { "SCE_HJ_COMMENTLINE", 43 }, + { "SCE_HJ_DEFAULT", 41 }, + { "SCE_HJ_DOUBLESTRING", 48 }, + { "SCE_HJ_KEYWORD", 47 }, + { "SCE_HJ_NUMBER", 45 }, + { "SCE_HJ_REGEX", 52 }, + { "SCE_HJ_SINGLESTRING", 49 }, + { "SCE_HJ_START", 40 }, + { "SCE_HJ_STRINGEOL", 51 }, + { "SCE_HJ_SYMBOLS", 50 }, + { "SCE_HJ_WORD", 46 }, + { "SCE_HPA_CHARACTER", 110 }, + { "SCE_HPA_CLASSNAME", 114 }, + { "SCE_HPA_COMMENTLINE", 107 }, + { "SCE_HPA_DEFAULT", 106 }, + { "SCE_HPA_DEFNAME", 115 }, + { "SCE_HPA_IDENTIFIER", 117 }, + { "SCE_HPA_NUMBER", 108 }, + { "SCE_HPA_OPERATOR", 116 }, + { "SCE_HPA_START", 105 }, + { "SCE_HPA_STRING", 109 }, + { "SCE_HPA_TRIPLE", 112 }, + { "SCE_HPA_TRIPLEDOUBLE", 113 }, + { "SCE_HPA_WORD", 111 }, + { "SCE_HPHP_COMMENT", 124 }, + { "SCE_HPHP_COMMENTLINE", 125 }, + { "SCE_HPHP_COMPLEX_VARIABLE", 104 }, + { "SCE_HPHP_DEFAULT", 118 }, + { "SCE_HPHP_HSTRING", 119 }, + { "SCE_HPHP_HSTRING_VARIABLE", 126 }, + { "SCE_HPHP_NUMBER", 122 }, + { "SCE_HPHP_OPERATOR", 127 }, + { "SCE_HPHP_SIMPLESTRING", 120 }, + { "SCE_HPHP_VARIABLE", 123 }, + { "SCE_HPHP_WORD", 121 }, + { "SCE_HP_CHARACTER", 95 }, + { "SCE_HP_CLASSNAME", 99 }, + { "SCE_HP_COMMENTLINE", 92 }, + { "SCE_HP_DEFAULT", 91 }, + { "SCE_HP_DEFNAME", 100 }, + { "SCE_HP_IDENTIFIER", 102 }, + { "SCE_HP_NUMBER", 93 }, + { "SCE_HP_OPERATOR", 101 }, + { "SCE_HP_START", 90 }, + { "SCE_HP_STRING", 94 }, + { "SCE_HP_TRIPLE", 97 }, + { "SCE_HP_TRIPLEDOUBLE", 98 }, + { "SCE_HP_WORD", 96 }, + { "SCE_H_ASP", 15 }, + { "SCE_H_ASPAT", 16 }, + { "SCE_H_ATTRIBUTE", 3 }, + { "SCE_H_ATTRIBUTEUNKNOWN", 4 }, + { "SCE_H_CDATA", 17 }, + { "SCE_H_COMMENT", 9 }, + { "SCE_H_DEFAULT", 0 }, + { "SCE_H_DOUBLESTRING", 6 }, + { "SCE_H_ENTITY", 10 }, + { "SCE_H_NUMBER", 5 }, + { "SCE_H_OTHER", 8 }, + { "SCE_H_QUESTION", 18 }, + { "SCE_H_SCRIPT", 14 }, + { "SCE_H_SGML_1ST_PARAM", 23 }, + { "SCE_H_SGML_1ST_PARAM_COMMENT", 30 }, + { "SCE_H_SGML_BLOCK_DEFAULT", 31 }, + { "SCE_H_SGML_COMMAND", 22 }, + { "SCE_H_SGML_COMMENT", 29 }, + { "SCE_H_SGML_DEFAULT", 21 }, + { "SCE_H_SGML_DOUBLESTRING", 24 }, + { "SCE_H_SGML_ENTITY", 28 }, + { "SCE_H_SGML_ERROR", 26 }, + { "SCE_H_SGML_SIMPLESTRING", 25 }, + { "SCE_H_SGML_SPECIAL", 27 }, + { "SCE_H_SINGLESTRING", 7 }, + { "SCE_H_TAG", 1 }, + { "SCE_H_TAGEND", 11 }, + { "SCE_H_TAGUNKNOWN", 2 }, + { "SCE_H_VALUE", 19 }, + { "SCE_H_XCCOMMENT", 20 }, + { "SCE_H_XMLEND", 13 }, + { "SCE_H_XMLSTART", 12 }, + { "SCE_INNO_COMMENT", 1 }, + { "SCE_INNO_COMMENT_PASCAL", 7 }, + { "SCE_INNO_DEFAULT", 0 }, + { "SCE_INNO_IDENTIFIER", 12 }, + { "SCE_INNO_INLINE_EXPANSION", 6 }, + { "SCE_INNO_KEYWORD", 2 }, + { "SCE_INNO_KEYWORD_PASCAL", 8 }, + { "SCE_INNO_KEYWORD_USER", 9 }, + { "SCE_INNO_PARAMETER", 3 }, + { "SCE_INNO_PREPROC", 5 }, + { "SCE_INNO_SECTION", 4 }, + { "SCE_INNO_STRING_DOUBLE", 10 }, + { "SCE_INNO_STRING_SINGLE", 11 }, + { "SCE_JSON_BLOCKCOMMENT", 7 }, + { "SCE_JSON_COMPACTIRI", 10 }, + { "SCE_JSON_DEFAULT", 0 }, + { "SCE_JSON_ERROR", 13 }, + { "SCE_JSON_ESCAPESEQUENCE", 5 }, + { "SCE_JSON_KEYWORD", 11 }, + { "SCE_JSON_LDKEYWORD", 12 }, + { "SCE_JSON_LINECOMMENT", 6 }, + { "SCE_JSON_NUMBER", 1 }, + { "SCE_JSON_OPERATOR", 8 }, + { "SCE_JSON_PROPERTYNAME", 4 }, + { "SCE_JSON_STRING", 2 }, + { "SCE_JSON_STRINGEOL", 3 }, + { "SCE_JSON_URI", 9 }, + { "SCE_KIX_COMMENT", 1 }, + { "SCE_KIX_COMMENTSTREAM", 10 }, + { "SCE_KIX_DEFAULT", 0 }, + { "SCE_KIX_FUNCTIONS", 8 }, + { "SCE_KIX_IDENTIFIER", 31 }, + { "SCE_KIX_KEYWORD", 7 }, + { "SCE_KIX_MACRO", 6 }, + { "SCE_KIX_NUMBER", 4 }, + { "SCE_KIX_OPERATOR", 9 }, + { "SCE_KIX_STRING1", 2 }, + { "SCE_KIX_STRING2", 3 }, + { "SCE_KIX_VAR", 5 }, + { "SCE_KVIRC_COMMENT", 1 }, + { "SCE_KVIRC_COMMENTBLOCK", 2 }, + { "SCE_KVIRC_DEFAULT", 0 }, + { "SCE_KVIRC_FUNCTION", 7 }, + { "SCE_KVIRC_FUNCTION_KEYWORD", 6 }, + { "SCE_KVIRC_KEYWORD", 5 }, + { "SCE_KVIRC_NUMBER", 9 }, + { "SCE_KVIRC_OPERATOR", 10 }, + { "SCE_KVIRC_STRING", 3 }, + { "SCE_KVIRC_STRING_FUNCTION", 11 }, + { "SCE_KVIRC_STRING_VARIABLE", 12 }, + { "SCE_KVIRC_VARIABLE", 8 }, + { "SCE_KVIRC_WORD", 4 }, + { "SCE_LISP_COMMENT", 1 }, + { "SCE_LISP_DEFAULT", 0 }, + { "SCE_LISP_IDENTIFIER", 9 }, + { "SCE_LISP_KEYWORD", 3 }, + { "SCE_LISP_KEYWORD_KW", 4 }, + { "SCE_LISP_MULTI_COMMENT", 12 }, + { "SCE_LISP_NUMBER", 2 }, + { "SCE_LISP_OPERATOR", 10 }, + { "SCE_LISP_SPECIAL", 11 }, + { "SCE_LISP_STRING", 6 }, + { "SCE_LISP_STRINGEOL", 8 }, + { "SCE_LISP_SYMBOL", 5 }, + { "SCE_LOT_ABORT", 6 }, + { "SCE_LOT_BREAK", 2 }, + { "SCE_LOT_DEFAULT", 0 }, + { "SCE_LOT_FAIL", 5 }, + { "SCE_LOT_HEADER", 1 }, + { "SCE_LOT_PASS", 4 }, + { "SCE_LOT_SET", 3 }, + { "SCE_LOUT_COMMENT", 1 }, + { "SCE_LOUT_DEFAULT", 0 }, + { "SCE_LOUT_IDENTIFIER", 9 }, + { "SCE_LOUT_NUMBER", 2 }, + { "SCE_LOUT_OPERATOR", 8 }, + { "SCE_LOUT_STRING", 7 }, + { "SCE_LOUT_STRINGEOL", 10 }, + { "SCE_LOUT_WORD", 3 }, + { "SCE_LOUT_WORD2", 4 }, + { "SCE_LOUT_WORD3", 5 }, + { "SCE_LOUT_WORD4", 6 }, + { "SCE_LUA_CHARACTER", 7 }, + { "SCE_LUA_COMMENT", 1 }, + { "SCE_LUA_COMMENTDOC", 3 }, + { "SCE_LUA_COMMENTLINE", 2 }, + { "SCE_LUA_DEFAULT", 0 }, + { "SCE_LUA_IDENTIFIER", 11 }, + { "SCE_LUA_LABEL", 20 }, + { "SCE_LUA_LITERALSTRING", 8 }, + { "SCE_LUA_NUMBER", 4 }, + { "SCE_LUA_OPERATOR", 10 }, + { "SCE_LUA_PREPROCESSOR", 9 }, + { "SCE_LUA_STRING", 6 }, + { "SCE_LUA_STRINGEOL", 12 }, + { "SCE_LUA_WORD", 5 }, + { "SCE_LUA_WORD2", 13 }, + { "SCE_LUA_WORD3", 14 }, + { "SCE_LUA_WORD4", 15 }, + { "SCE_LUA_WORD5", 16 }, + { "SCE_LUA_WORD6", 17 }, + { "SCE_LUA_WORD7", 18 }, + { "SCE_LUA_WORD8", 19 }, + { "SCE_L_CMDOPT", 11 }, + { "SCE_L_COMMAND", 1 }, + { "SCE_L_COMMENT", 4 }, + { "SCE_L_COMMENT2", 7 }, + { "SCE_L_DEFAULT", 0 }, + { "SCE_L_ERROR", 12 }, + { "SCE_L_MATH", 3 }, + { "SCE_L_MATH2", 6 }, + { "SCE_L_SHORTCMD", 9 }, + { "SCE_L_SPECIAL", 10 }, + { "SCE_L_TAG", 2 }, + { "SCE_L_TAG2", 5 }, + { "SCE_L_VERBATIM", 8 }, + { "SCE_MAGIK_BRACE_BLOCK", 10 }, + { "SCE_MAGIK_BRACKET_BLOCK", 9 }, + { "SCE_MAGIK_CHARACTER", 3 }, + { "SCE_MAGIK_COMMENT", 1 }, + { "SCE_MAGIK_CONTAINER", 8 }, + { "SCE_MAGIK_DEFAULT", 0 }, + { "SCE_MAGIK_FLOW", 7 }, + { "SCE_MAGIK_HYPER_COMMENT", 16 }, + { "SCE_MAGIK_IDENTIFIER", 5 }, + { "SCE_MAGIK_KEYWORD", 13 }, + { "SCE_MAGIK_NUMBER", 4 }, + { "SCE_MAGIK_OPERATOR", 6 }, + { "SCE_MAGIK_PRAGMA", 14 }, + { "SCE_MAGIK_SQBRACKET_BLOCK", 11 }, + { "SCE_MAGIK_STRING", 2 }, + { "SCE_MAGIK_SYMBOL", 15 }, + { "SCE_MAGIK_UNKNOWN_KEYWORD", 12 }, + { "SCE_MAKE_COMMENT", 1 }, + { "SCE_MAKE_DEFAULT", 0 }, + { "SCE_MAKE_IDENTIFIER", 3 }, + { "SCE_MAKE_IDEOL", 9 }, + { "SCE_MAKE_OPERATOR", 4 }, + { "SCE_MAKE_PREPROCESSOR", 2 }, + { "SCE_MAKE_TARGET", 5 }, + { "SCE_MARKDOWN_BLOCKQUOTE", 15 }, + { "SCE_MARKDOWN_CODE", 19 }, + { "SCE_MARKDOWN_CODE2", 20 }, + { "SCE_MARKDOWN_CODEBK", 21 }, + { "SCE_MARKDOWN_DEFAULT", 0 }, + { "SCE_MARKDOWN_EM1", 4 }, + { "SCE_MARKDOWN_EM2", 5 }, + { "SCE_MARKDOWN_HEADER1", 6 }, + { "SCE_MARKDOWN_HEADER2", 7 }, + { "SCE_MARKDOWN_HEADER3", 8 }, + { "SCE_MARKDOWN_HEADER4", 9 }, + { "SCE_MARKDOWN_HEADER5", 10 }, + { "SCE_MARKDOWN_HEADER6", 11 }, + { "SCE_MARKDOWN_HRULE", 17 }, + { "SCE_MARKDOWN_LINE_BEGIN", 1 }, + { "SCE_MARKDOWN_LINK", 18 }, + { "SCE_MARKDOWN_OLIST_ITEM", 14 }, + { "SCE_MARKDOWN_PRECHAR", 12 }, + { "SCE_MARKDOWN_STRIKEOUT", 16 }, + { "SCE_MARKDOWN_STRONG1", 2 }, + { "SCE_MARKDOWN_STRONG2", 3 }, + { "SCE_MARKDOWN_ULIST_ITEM", 13 }, + { "SCE_MATLAB_COMMAND", 2 }, + { "SCE_MATLAB_COMMENT", 1 }, + { "SCE_MATLAB_DEFAULT", 0 }, + { "SCE_MATLAB_DOUBLEQUOTESTRING", 8 }, + { "SCE_MATLAB_IDENTIFIER", 7 }, + { "SCE_MATLAB_KEYWORD", 4 }, + { "SCE_MATLAB_NUMBER", 3 }, + { "SCE_MATLAB_OPERATOR", 6 }, + { "SCE_MATLAB_STRING", 5 }, + { "SCE_MAXIMA_COMMAND", 5 }, + { "SCE_MAXIMA_COMMANDENDING", 1 }, + { "SCE_MAXIMA_COMMENT", 2 }, + { "SCE_MAXIMA_NUMBER", 3 }, + { "SCE_MAXIMA_OPERATOR", 0 }, + { "SCE_MAXIMA_STRING", 4 }, + { "SCE_MAXIMA_UNKNOWN", 7 }, + { "SCE_MAXIMA_VARIABLE", 6 }, + { "SCE_METAPOST_COMMAND", 4 }, + { "SCE_METAPOST_DEFAULT", 0 }, + { "SCE_METAPOST_EXTRA", 6 }, + { "SCE_METAPOST_GROUP", 2 }, + { "SCE_METAPOST_SPECIAL", 1 }, + { "SCE_METAPOST_SYMBOL", 3 }, + { "SCE_METAPOST_TEXT", 5 }, + { "SCE_MMIXAL_CHAR", 11 }, + { "SCE_MMIXAL_COMMENT", 1 }, + { "SCE_MMIXAL_HEX", 14 }, + { "SCE_MMIXAL_INCLUDE", 17 }, + { "SCE_MMIXAL_LABEL", 2 }, + { "SCE_MMIXAL_LEADWS", 0 }, + { "SCE_MMIXAL_NUMBER", 9 }, + { "SCE_MMIXAL_OPCODE", 3 }, + { "SCE_MMIXAL_OPCODE_POST", 7 }, + { "SCE_MMIXAL_OPCODE_PRE", 4 }, + { "SCE_MMIXAL_OPCODE_UNKNOWN", 6 }, + { "SCE_MMIXAL_OPCODE_VALID", 5 }, + { "SCE_MMIXAL_OPERANDS", 8 }, + { "SCE_MMIXAL_OPERATOR", 15 }, + { "SCE_MMIXAL_REF", 10 }, + { "SCE_MMIXAL_REGISTER", 13 }, + { "SCE_MMIXAL_STRING", 12 }, + { "SCE_MMIXAL_SYMBOL", 16 }, + { "SCE_MODULA_BADSTR", 17 }, + { "SCE_MODULA_BASENUM", 7 }, + { "SCE_MODULA_CHAR", 11 }, + { "SCE_MODULA_CHARSPEC", 12 }, + { "SCE_MODULA_COMMENT", 1 }, + { "SCE_MODULA_DEFAULT", 0 }, + { "SCE_MODULA_DOXYCOMM", 2 }, + { "SCE_MODULA_DOXYKEY", 3 }, + { "SCE_MODULA_FLOAT", 8 }, + { "SCE_MODULA_KEYWORD", 4 }, + { "SCE_MODULA_NUMBER", 6 }, + { "SCE_MODULA_OPERATOR", 16 }, + { "SCE_MODULA_PRAGMA", 14 }, + { "SCE_MODULA_PRGKEY", 15 }, + { "SCE_MODULA_PROC", 13 }, + { "SCE_MODULA_RESERVED", 5 }, + { "SCE_MODULA_STRING", 9 }, + { "SCE_MODULA_STRSPEC", 10 }, + { "SCE_MSSQL_COLUMN_NAME", 8 }, + { "SCE_MSSQL_COLUMN_NAME_2", 16 }, + { "SCE_MSSQL_COMMENT", 1 }, + { "SCE_MSSQL_DATATYPE", 10 }, + { "SCE_MSSQL_DEFAULT", 0 }, + { "SCE_MSSQL_DEFAULT_PREF_DATATYPE", 15 }, + { "SCE_MSSQL_FUNCTION", 13 }, + { "SCE_MSSQL_GLOBAL_VARIABLE", 12 }, + { "SCE_MSSQL_IDENTIFIER", 6 }, + { "SCE_MSSQL_LINE_COMMENT", 2 }, + { "SCE_MSSQL_NUMBER", 3 }, + { "SCE_MSSQL_OPERATOR", 5 }, + { "SCE_MSSQL_STATEMENT", 9 }, + { "SCE_MSSQL_STORED_PROCEDURE", 14 }, + { "SCE_MSSQL_STRING", 4 }, + { "SCE_MSSQL_SYSTABLE", 11 }, + { "SCE_MSSQL_VARIABLE", 7 }, + { "SCE_MYSQL_COMMENT", 1 }, + { "SCE_MYSQL_COMMENTLINE", 2 }, + { "SCE_MYSQL_DATABASEOBJECT", 9 }, + { "SCE_MYSQL_DEFAULT", 0 }, + { "SCE_MYSQL_DQSTRING", 13 }, + { "SCE_MYSQL_FUNCTION", 15 }, + { "SCE_MYSQL_HIDDENCOMMAND", 21 }, + { "SCE_MYSQL_IDENTIFIER", 16 }, + { "SCE_MYSQL_KEYWORD", 8 }, + { "SCE_MYSQL_KNOWNSYSTEMVARIABLE", 5 }, + { "SCE_MYSQL_MAJORKEYWORD", 7 }, + { "SCE_MYSQL_NUMBER", 6 }, + { "SCE_MYSQL_OPERATOR", 14 }, + { "SCE_MYSQL_PLACEHOLDER", 22 }, + { "SCE_MYSQL_PROCEDUREKEYWORD", 10 }, + { "SCE_MYSQL_QUOTEDIDENTIFIER", 17 }, + { "SCE_MYSQL_SQSTRING", 12 }, + { "SCE_MYSQL_STRING", 11 }, + { "SCE_MYSQL_SYSTEMVARIABLE", 4 }, + { "SCE_MYSQL_USER1", 18 }, + { "SCE_MYSQL_USER2", 19 }, + { "SCE_MYSQL_USER3", 20 }, + { "SCE_MYSQL_VARIABLE", 3 }, + { "SCE_NIM_BACKTICKS", 11 }, + { "SCE_NIM_CHARACTER", 7 }, + { "SCE_NIM_COMMENT", 1 }, + { "SCE_NIM_COMMENTDOC", 2 }, + { "SCE_NIM_COMMENTLINE", 3 }, + { "SCE_NIM_COMMENTLINEDOC", 4 }, + { "SCE_NIM_DEFAULT", 0 }, + { "SCE_NIM_FUNCNAME", 12 }, + { "SCE_NIM_IDENTIFIER", 16 }, + { "SCE_NIM_NUMBER", 5 }, + { "SCE_NIM_NUMERROR", 14 }, + { "SCE_NIM_OPERATOR", 15 }, + { "SCE_NIM_STRING", 6 }, + { "SCE_NIM_STRINGEOL", 13 }, + { "SCE_NIM_TRIPLE", 9 }, + { "SCE_NIM_TRIPLEDOUBLE", 10 }, + { "SCE_NIM_WORD", 8 }, + { "SCE_NNCRONTAB_ASTERISK", 6 }, + { "SCE_NNCRONTAB_COMMENT", 1 }, + { "SCE_NNCRONTAB_DEFAULT", 0 }, + { "SCE_NNCRONTAB_ENVIRONMENT", 9 }, + { "SCE_NNCRONTAB_IDENTIFIER", 10 }, + { "SCE_NNCRONTAB_KEYWORD", 4 }, + { "SCE_NNCRONTAB_MODIFIER", 5 }, + { "SCE_NNCRONTAB_NUMBER", 7 }, + { "SCE_NNCRONTAB_SECTION", 3 }, + { "SCE_NNCRONTAB_STRING", 8 }, + { "SCE_NNCRONTAB_TASK", 2 }, + { "SCE_NSIS_COMMENT", 1 }, + { "SCE_NSIS_COMMENTBOX", 18 }, + { "SCE_NSIS_DEFAULT", 0 }, + { "SCE_NSIS_FUNCTION", 5 }, + { "SCE_NSIS_FUNCTIONDEF", 17 }, + { "SCE_NSIS_IFDEFINEDEF", 11 }, + { "SCE_NSIS_LABEL", 7 }, + { "SCE_NSIS_MACRODEF", 12 }, + { "SCE_NSIS_NUMBER", 14 }, + { "SCE_NSIS_PAGEEX", 16 }, + { "SCE_NSIS_SECTIONDEF", 9 }, + { "SCE_NSIS_SECTIONGROUP", 15 }, + { "SCE_NSIS_STRINGDQ", 2 }, + { "SCE_NSIS_STRINGLQ", 3 }, + { "SCE_NSIS_STRINGRQ", 4 }, + { "SCE_NSIS_STRINGVAR", 13 }, + { "SCE_NSIS_SUBSECTIONDEF", 10 }, + { "SCE_NSIS_USERDEFINED", 8 }, + { "SCE_NSIS_VARIABLE", 6 }, + { "SCE_OPAL_BOOL_CONST", 8 }, + { "SCE_OPAL_COMMENT_BLOCK", 1 }, + { "SCE_OPAL_COMMENT_LINE", 2 }, + { "SCE_OPAL_DEFAULT", 32 }, + { "SCE_OPAL_INTEGER", 3 }, + { "SCE_OPAL_KEYWORD", 4 }, + { "SCE_OPAL_PAR", 7 }, + { "SCE_OPAL_SORT", 5 }, + { "SCE_OPAL_SPACE", 0 }, + { "SCE_OPAL_STRING", 6 }, + { "SCE_OSCRIPT_BLOCK_COMMENT", 2 }, + { "SCE_OSCRIPT_CONSTANT", 8 }, + { "SCE_OSCRIPT_DEFAULT", 0 }, + { "SCE_OSCRIPT_DOC_COMMENT", 3 }, + { "SCE_OSCRIPT_DOUBLEQUOTE_STRING", 7 }, + { "SCE_OSCRIPT_FUNCTION", 15 }, + { "SCE_OSCRIPT_GLOBAL", 10 }, + { "SCE_OSCRIPT_IDENTIFIER", 9 }, + { "SCE_OSCRIPT_KEYWORD", 11 }, + { "SCE_OSCRIPT_LABEL", 13 }, + { "SCE_OSCRIPT_LINE_COMMENT", 1 }, + { "SCE_OSCRIPT_METHOD", 18 }, + { "SCE_OSCRIPT_NUMBER", 5 }, + { "SCE_OSCRIPT_OBJECT", 16 }, + { "SCE_OSCRIPT_OPERATOR", 12 }, + { "SCE_OSCRIPT_PREPROCESSOR", 4 }, + { "SCE_OSCRIPT_PROPERTY", 17 }, + { "SCE_OSCRIPT_SINGLEQUOTE_STRING", 6 }, + { "SCE_OSCRIPT_TYPE", 14 }, + { "SCE_PAS_ASM", 14 }, + { "SCE_PAS_CHARACTER", 12 }, + { "SCE_PAS_COMMENT", 2 }, + { "SCE_PAS_COMMENT2", 3 }, + { "SCE_PAS_COMMENTLINE", 4 }, + { "SCE_PAS_DEFAULT", 0 }, + { "SCE_PAS_HEXNUMBER", 8 }, + { "SCE_PAS_IDENTIFIER", 1 }, + { "SCE_PAS_NUMBER", 7 }, + { "SCE_PAS_OPERATOR", 13 }, + { "SCE_PAS_PREPROCESSOR", 5 }, + { "SCE_PAS_PREPROCESSOR2", 6 }, + { "SCE_PAS_STRING", 10 }, + { "SCE_PAS_STRINGEOL", 11 }, + { "SCE_PAS_WORD", 9 }, + { "SCE_PLM_COMMENT", 1 }, + { "SCE_PLM_CONTROL", 6 }, + { "SCE_PLM_DEFAULT", 0 }, + { "SCE_PLM_IDENTIFIER", 4 }, + { "SCE_PLM_KEYWORD", 7 }, + { "SCE_PLM_NUMBER", 3 }, + { "SCE_PLM_OPERATOR", 5 }, + { "SCE_PLM_STRING", 2 }, + { "SCE_PL_ARRAY", 13 }, + { "SCE_PL_BACKTICKS", 20 }, + { "SCE_PL_BACKTICKS_VAR", 57 }, + { "SCE_PL_CHARACTER", 7 }, + { "SCE_PL_COMMENTLINE", 2 }, + { "SCE_PL_DATASECTION", 21 }, + { "SCE_PL_DEFAULT", 0 }, + { "SCE_PL_ERROR", 1 }, + { "SCE_PL_FORMAT", 42 }, + { "SCE_PL_FORMAT_IDENT", 41 }, + { "SCE_PL_HASH", 14 }, + { "SCE_PL_HERE_DELIM", 22 }, + { "SCE_PL_HERE_Q", 23 }, + { "SCE_PL_HERE_QQ", 24 }, + { "SCE_PL_HERE_QQ_VAR", 61 }, + { "SCE_PL_HERE_QX", 25 }, + { "SCE_PL_HERE_QX_VAR", 62 }, + { "SCE_PL_IDENTIFIER", 11 }, + { "SCE_PL_LONGQUOTE", 19 }, + { "SCE_PL_NUMBER", 4 }, + { "SCE_PL_OPERATOR", 10 }, + { "SCE_PL_POD", 3 }, + { "SCE_PL_POD_VERB", 31 }, + { "SCE_PL_PREPROCESSOR", 9 }, + { "SCE_PL_PUNCTUATION", 8 }, + { "SCE_PL_REGEX", 17 }, + { "SCE_PL_REGEX_VAR", 54 }, + { "SCE_PL_REGSUBST", 18 }, + { "SCE_PL_REGSUBST_VAR", 55 }, + { "SCE_PL_SCALAR", 12 }, + { "SCE_PL_STRING", 6 }, + { "SCE_PL_STRING_Q", 26 }, + { "SCE_PL_STRING_QQ", 27 }, + { "SCE_PL_STRING_QQ_VAR", 64 }, + { "SCE_PL_STRING_QR", 29 }, + { "SCE_PL_STRING_QR_VAR", 66 }, + { "SCE_PL_STRING_QW", 30 }, + { "SCE_PL_STRING_QX", 28 }, + { "SCE_PL_STRING_QX_VAR", 65 }, + { "SCE_PL_STRING_VAR", 43 }, + { "SCE_PL_SUB_PROTOTYPE", 40 }, + { "SCE_PL_SYMBOLTABLE", 15 }, + { "SCE_PL_VARIABLE_INDEXER", 16 }, + { "SCE_PL_WORD", 5 }, + { "SCE_PL_XLAT", 44 }, + { "SCE_POV_BADDIRECTIVE", 9 }, + { "SCE_POV_COMMENT", 1 }, + { "SCE_POV_COMMENTLINE", 2 }, + { "SCE_POV_DEFAULT", 0 }, + { "SCE_POV_DIRECTIVE", 8 }, + { "SCE_POV_IDENTIFIER", 5 }, + { "SCE_POV_NUMBER", 3 }, + { "SCE_POV_OPERATOR", 4 }, + { "SCE_POV_STRING", 6 }, + { "SCE_POV_STRINGEOL", 7 }, + { "SCE_POV_WORD2", 10 }, + { "SCE_POV_WORD3", 11 }, + { "SCE_POV_WORD4", 12 }, + { "SCE_POV_WORD5", 13 }, + { "SCE_POV_WORD6", 14 }, + { "SCE_POV_WORD7", 15 }, + { "SCE_POV_WORD8", 16 }, + { "SCE_POWERPRO_ALTQUOTE", 15 }, + { "SCE_POWERPRO_COMMENTBLOCK", 1 }, + { "SCE_POWERPRO_COMMENTLINE", 2 }, + { "SCE_POWERPRO_DEFAULT", 0 }, + { "SCE_POWERPRO_DOUBLEQUOTEDSTRING", 8 }, + { "SCE_POWERPRO_FUNCTION", 16 }, + { "SCE_POWERPRO_IDENTIFIER", 12 }, + { "SCE_POWERPRO_LINECONTINUE", 10 }, + { "SCE_POWERPRO_NUMBER", 3 }, + { "SCE_POWERPRO_OPERATOR", 11 }, + { "SCE_POWERPRO_SINGLEQUOTEDSTRING", 9 }, + { "SCE_POWERPRO_STRINGEOL", 13 }, + { "SCE_POWERPRO_VERBATIM", 14 }, + { "SCE_POWERPRO_WORD", 4 }, + { "SCE_POWERPRO_WORD2", 5 }, + { "SCE_POWERPRO_WORD3", 6 }, + { "SCE_POWERPRO_WORD4", 7 }, + { "SCE_POWERSHELL_ALIAS", 10 }, + { "SCE_POWERSHELL_CHARACTER", 3 }, + { "SCE_POWERSHELL_CMDLET", 9 }, + { "SCE_POWERSHELL_COMMENT", 1 }, + { "SCE_POWERSHELL_COMMENTDOCKEYWORD", 16 }, + { "SCE_POWERSHELL_COMMENTSTREAM", 13 }, + { "SCE_POWERSHELL_DEFAULT", 0 }, + { "SCE_POWERSHELL_FUNCTION", 11 }, + { "SCE_POWERSHELL_HERE_CHARACTER", 15 }, + { "SCE_POWERSHELL_HERE_STRING", 14 }, + { "SCE_POWERSHELL_IDENTIFIER", 7 }, + { "SCE_POWERSHELL_KEYWORD", 8 }, + { "SCE_POWERSHELL_NUMBER", 4 }, + { "SCE_POWERSHELL_OPERATOR", 6 }, + { "SCE_POWERSHELL_STRING", 2 }, + { "SCE_POWERSHELL_USER1", 12 }, + { "SCE_POWERSHELL_VARIABLE", 5 }, + { "SCE_PO_COMMENT", 1 }, + { "SCE_PO_DEFAULT", 0 }, + { "SCE_PO_ERROR", 15 }, + { "SCE_PO_FLAGS", 11 }, + { "SCE_PO_FUZZY", 8 }, + { "SCE_PO_MSGCTXT", 6 }, + { "SCE_PO_MSGCTXT_TEXT", 7 }, + { "SCE_PO_MSGCTXT_TEXT_EOL", 14 }, + { "SCE_PO_MSGID", 2 }, + { "SCE_PO_MSGID_TEXT", 3 }, + { "SCE_PO_MSGID_TEXT_EOL", 12 }, + { "SCE_PO_MSGSTR", 4 }, + { "SCE_PO_MSGSTR_TEXT", 5 }, + { "SCE_PO_MSGSTR_TEXT_EOL", 13 }, + { "SCE_PO_PROGRAMMER_COMMENT", 9 }, + { "SCE_PO_REFERENCE", 10 }, + { "SCE_PROPS_ASSIGNMENT", 3 }, + { "SCE_PROPS_COMMENT", 1 }, + { "SCE_PROPS_DEFAULT", 0 }, + { "SCE_PROPS_DEFVAL", 4 }, + { "SCE_PROPS_KEY", 5 }, + { "SCE_PROPS_SECTION", 2 }, + { "SCE_PS_BADSTRINGCHAR", 15 }, + { "SCE_PS_BASE85STRING", 14 }, + { "SCE_PS_COMMENT", 1 }, + { "SCE_PS_DEFAULT", 0 }, + { "SCE_PS_DSC_COMMENT", 2 }, + { "SCE_PS_DSC_VALUE", 3 }, + { "SCE_PS_HEXSTRING", 13 }, + { "SCE_PS_IMMEVAL", 8 }, + { "SCE_PS_KEYWORD", 6 }, + { "SCE_PS_LITERAL", 7 }, + { "SCE_PS_NAME", 5 }, + { "SCE_PS_NUMBER", 4 }, + { "SCE_PS_PAREN_ARRAY", 9 }, + { "SCE_PS_PAREN_DICT", 10 }, + { "SCE_PS_PAREN_PROC", 11 }, + { "SCE_PS_TEXT", 12 }, + { "SCE_P_CHARACTER", 4 }, + { "SCE_P_CLASSNAME", 8 }, + { "SCE_P_COMMENTBLOCK", 12 }, + { "SCE_P_COMMENTLINE", 1 }, + { "SCE_P_DECORATOR", 15 }, + { "SCE_P_DEFAULT", 0 }, + { "SCE_P_DEFNAME", 9 }, + { "SCE_P_FCHARACTER", 17 }, + { "SCE_P_FSTRING", 16 }, + { "SCE_P_FTRIPLE", 18 }, + { "SCE_P_FTRIPLEDOUBLE", 19 }, + { "SCE_P_IDENTIFIER", 11 }, + { "SCE_P_NUMBER", 2 }, + { "SCE_P_OPERATOR", 10 }, + { "SCE_P_STRING", 3 }, + { "SCE_P_STRINGEOL", 13 }, + { "SCE_P_TRIPLE", 6 }, + { "SCE_P_TRIPLEDOUBLE", 7 }, + { "SCE_P_WORD", 5 }, + { "SCE_P_WORD2", 14 }, + { "SCE_RB_BACKTICKS", 18 }, + { "SCE_RB_CHARACTER", 7 }, + { "SCE_RB_CLASSNAME", 8 }, + { "SCE_RB_CLASS_VAR", 17 }, + { "SCE_RB_COMMENTLINE", 2 }, + { "SCE_RB_DATASECTION", 19 }, + { "SCE_RB_DEFAULT", 0 }, + { "SCE_RB_DEFNAME", 9 }, + { "SCE_RB_ERROR", 1 }, + { "SCE_RB_GLOBAL", 13 }, + { "SCE_RB_HERE_DELIM", 20 }, + { "SCE_RB_HERE_Q", 21 }, + { "SCE_RB_HERE_QQ", 22 }, + { "SCE_RB_HERE_QX", 23 }, + { "SCE_RB_IDENTIFIER", 11 }, + { "SCE_RB_INSTANCE_VAR", 16 }, + { "SCE_RB_MODULE_NAME", 15 }, + { "SCE_RB_NUMBER", 4 }, + { "SCE_RB_OPERATOR", 10 }, + { "SCE_RB_POD", 3 }, + { "SCE_RB_REGEX", 12 }, + { "SCE_RB_STDERR", 40 }, + { "SCE_RB_STDIN", 30 }, + { "SCE_RB_STDOUT", 31 }, + { "SCE_RB_STRING", 6 }, + { "SCE_RB_STRING_Q", 24 }, + { "SCE_RB_STRING_QQ", 25 }, + { "SCE_RB_STRING_QR", 27 }, + { "SCE_RB_STRING_QW", 28 }, + { "SCE_RB_STRING_QX", 26 }, + { "SCE_RB_SYMBOL", 14 }, + { "SCE_RB_UPPER_BOUND", 41 }, + { "SCE_RB_WORD", 5 }, + { "SCE_RB_WORD_DEMOTED", 29 }, + { "SCE_REBOL_BINARY", 11 }, + { "SCE_REBOL_BRACEDSTRING", 7 }, + { "SCE_REBOL_CHARACTER", 5 }, + { "SCE_REBOL_COMMENTBLOCK", 2 }, + { "SCE_REBOL_COMMENTLINE", 1 }, + { "SCE_REBOL_DATE", 18 }, + { "SCE_REBOL_DEFAULT", 0 }, + { "SCE_REBOL_EMAIL", 16 }, + { "SCE_REBOL_FILE", 15 }, + { "SCE_REBOL_IDENTIFIER", 20 }, + { "SCE_REBOL_ISSUE", 13 }, + { "SCE_REBOL_MONEY", 12 }, + { "SCE_REBOL_NUMBER", 8 }, + { "SCE_REBOL_OPERATOR", 4 }, + { "SCE_REBOL_PAIR", 9 }, + { "SCE_REBOL_PREFACE", 3 }, + { "SCE_REBOL_QUOTEDSTRING", 6 }, + { "SCE_REBOL_TAG", 14 }, + { "SCE_REBOL_TIME", 19 }, + { "SCE_REBOL_TUPLE", 10 }, + { "SCE_REBOL_URL", 17 }, + { "SCE_REBOL_WORD", 21 }, + { "SCE_REBOL_WORD2", 22 }, + { "SCE_REBOL_WORD3", 23 }, + { "SCE_REBOL_WORD4", 24 }, + { "SCE_REBOL_WORD5", 25 }, + { "SCE_REBOL_WORD6", 26 }, + { "SCE_REBOL_WORD7", 27 }, + { "SCE_REBOL_WORD8", 28 }, + { "SCE_REG_ADDEDKEY", 6 }, + { "SCE_REG_COMMENT", 1 }, + { "SCE_REG_DEFAULT", 0 }, + { "SCE_REG_DELETEDKEY", 7 }, + { "SCE_REG_ESCAPED", 8 }, + { "SCE_REG_HEXDIGIT", 4 }, + { "SCE_REG_KEYPATH_GUID", 9 }, + { "SCE_REG_OPERATOR", 12 }, + { "SCE_REG_PARAMETER", 11 }, + { "SCE_REG_STRING", 3 }, + { "SCE_REG_STRING_GUID", 10 }, + { "SCE_REG_VALUENAME", 2 }, + { "SCE_REG_VALUETYPE", 5 }, + { "SCE_RUST_BYTECHARACTER", 23 }, + { "SCE_RUST_BYTESTRING", 21 }, + { "SCE_RUST_BYTESTRINGR", 22 }, + { "SCE_RUST_CHARACTER", 15 }, + { "SCE_RUST_COMMENTBLOCK", 1 }, + { "SCE_RUST_COMMENTBLOCKDOC", 3 }, + { "SCE_RUST_COMMENTLINE", 2 }, + { "SCE_RUST_COMMENTLINEDOC", 4 }, + { "SCE_RUST_DEFAULT", 0 }, + { "SCE_RUST_IDENTIFIER", 17 }, + { "SCE_RUST_LEXERROR", 20 }, + { "SCE_RUST_LIFETIME", 18 }, + { "SCE_RUST_MACRO", 19 }, + { "SCE_RUST_NUMBER", 5 }, + { "SCE_RUST_OPERATOR", 16 }, + { "SCE_RUST_STRING", 13 }, + { "SCE_RUST_STRINGR", 14 }, + { "SCE_RUST_WORD", 6 }, + { "SCE_RUST_WORD2", 7 }, + { "SCE_RUST_WORD3", 8 }, + { "SCE_RUST_WORD4", 9 }, + { "SCE_RUST_WORD5", 10 }, + { "SCE_RUST_WORD6", 11 }, + { "SCE_RUST_WORD7", 12 }, + { "SCE_R_BASEKWORD", 3 }, + { "SCE_R_COMMENT", 1 }, + { "SCE_R_DEFAULT", 0 }, + { "SCE_R_IDENTIFIER", 9 }, + { "SCE_R_INFIX", 10 }, + { "SCE_R_INFIXEOL", 11 }, + { "SCE_R_KWORD", 2 }, + { "SCE_R_NUMBER", 5 }, + { "SCE_R_OPERATOR", 8 }, + { "SCE_R_OTHERKWORD", 4 }, + { "SCE_R_STRING", 6 }, + { "SCE_R_STRING2", 7 }, + { "SCE_SAS_BLOCK_KEYWORD", 13 }, + { "SCE_SAS_COMMENT", 1 }, + { "SCE_SAS_COMMENTBLOCK", 3 }, + { "SCE_SAS_COMMENTLINE", 2 }, + { "SCE_SAS_DEFAULT", 0 }, + { "SCE_SAS_GLOBAL_MACRO", 10 }, + { "SCE_SAS_IDENTIFIER", 6 }, + { "SCE_SAS_MACRO", 11 }, + { "SCE_SAS_MACRO_FUNCTION", 14 }, + { "SCE_SAS_MACRO_KEYWORD", 12 }, + { "SCE_SAS_NUMBER", 4 }, + { "SCE_SAS_OPERATOR", 5 }, + { "SCE_SAS_STATEMENT", 15 }, + { "SCE_SAS_STRING", 7 }, + { "SCE_SAS_TYPE", 8 }, + { "SCE_SAS_WORD", 9 }, + { "SCE_SCRIPTOL_CHARACTER", 8 }, + { "SCE_SCRIPTOL_CLASSNAME", 14 }, + { "SCE_SCRIPTOL_COMMENTBLOCK", 5 }, + { "SCE_SCRIPTOL_COMMENTLINE", 2 }, + { "SCE_SCRIPTOL_CSTYLE", 4 }, + { "SCE_SCRIPTOL_DEFAULT", 0 }, + { "SCE_SCRIPTOL_IDENTIFIER", 12 }, + { "SCE_SCRIPTOL_KEYWORD", 10 }, + { "SCE_SCRIPTOL_NUMBER", 6 }, + { "SCE_SCRIPTOL_OPERATOR", 11 }, + { "SCE_SCRIPTOL_PERSISTENT", 3 }, + { "SCE_SCRIPTOL_PREPROCESSOR", 15 }, + { "SCE_SCRIPTOL_STRING", 7 }, + { "SCE_SCRIPTOL_STRINGEOL", 9 }, + { "SCE_SCRIPTOL_TRIPLE", 13 }, + { "SCE_SCRIPTOL_WHITE", 1 }, + { "SCE_SH_BACKTICKS", 11 }, + { "SCE_SH_CHARACTER", 6 }, + { "SCE_SH_COMMENTLINE", 2 }, + { "SCE_SH_DEFAULT", 0 }, + { "SCE_SH_ERROR", 1 }, + { "SCE_SH_HERE_DELIM", 12 }, + { "SCE_SH_HERE_Q", 13 }, + { "SCE_SH_IDENTIFIER", 8 }, + { "SCE_SH_NUMBER", 3 }, + { "SCE_SH_OPERATOR", 7 }, + { "SCE_SH_PARAM", 10 }, + { "SCE_SH_SCALAR", 9 }, + { "SCE_SH_STRING", 5 }, + { "SCE_SH_WORD", 4 }, + { "SCE_SML_CHAR", 9 }, + { "SCE_SML_COMMENT", 12 }, + { "SCE_SML_COMMENT1", 13 }, + { "SCE_SML_COMMENT2", 14 }, + { "SCE_SML_COMMENT3", 15 }, + { "SCE_SML_DEFAULT", 0 }, + { "SCE_SML_IDENTIFIER", 1 }, + { "SCE_SML_KEYWORD", 3 }, + { "SCE_SML_KEYWORD2", 4 }, + { "SCE_SML_KEYWORD3", 5 }, + { "SCE_SML_LINENUM", 6 }, + { "SCE_SML_NUMBER", 8 }, + { "SCE_SML_OPERATOR", 7 }, + { "SCE_SML_STRING", 11 }, + { "SCE_SML_TAGNAME", 2 }, + { "SCE_SN_CODE", 1 }, + { "SCE_SN_COMMENTLINE", 2 }, + { "SCE_SN_COMMENTLINEBANG", 3 }, + { "SCE_SN_DEFAULT", 0 }, + { "SCE_SN_IDENTIFIER", 11 }, + { "SCE_SN_NUMBER", 4 }, + { "SCE_SN_OPERATOR", 10 }, + { "SCE_SN_PREPROCESSOR", 9 }, + { "SCE_SN_REGEXTAG", 13 }, + { "SCE_SN_SIGNAL", 14 }, + { "SCE_SN_STRING", 6 }, + { "SCE_SN_STRINGEOL", 12 }, + { "SCE_SN_USER", 19 }, + { "SCE_SN_WORD", 5 }, + { "SCE_SN_WORD2", 7 }, + { "SCE_SN_WORD3", 8 }, + { "SCE_SORCUS_COMMAND", 1 }, + { "SCE_SORCUS_COMMENTLINE", 3 }, + { "SCE_SORCUS_CONSTANT", 9 }, + { "SCE_SORCUS_DEFAULT", 0 }, + { "SCE_SORCUS_IDENTIFIER", 6 }, + { "SCE_SORCUS_NUMBER", 8 }, + { "SCE_SORCUS_OPERATOR", 7 }, + { "SCE_SORCUS_PARAMETER", 2 }, + { "SCE_SORCUS_STRING", 4 }, + { "SCE_SORCUS_STRINGEOL", 5 }, + { "SCE_SPICE_COMMENTLINE", 8 }, + { "SCE_SPICE_DEFAULT", 0 }, + { "SCE_SPICE_DELIMITER", 6 }, + { "SCE_SPICE_IDENTIFIER", 1 }, + { "SCE_SPICE_KEYWORD", 2 }, + { "SCE_SPICE_KEYWORD2", 3 }, + { "SCE_SPICE_KEYWORD3", 4 }, + { "SCE_SPICE_NUMBER", 5 }, + { "SCE_SPICE_VALUE", 7 }, + { "SCE_SQL_CHARACTER", 7 }, + { "SCE_SQL_COMMENT", 1 }, + { "SCE_SQL_COMMENTDOC", 3 }, + { "SCE_SQL_COMMENTDOCKEYWORD", 17 }, + { "SCE_SQL_COMMENTDOCKEYWORDERROR", 18 }, + { "SCE_SQL_COMMENTLINE", 2 }, + { "SCE_SQL_COMMENTLINEDOC", 15 }, + { "SCE_SQL_DEFAULT", 0 }, + { "SCE_SQL_IDENTIFIER", 11 }, + { "SCE_SQL_NUMBER", 4 }, + { "SCE_SQL_OPERATOR", 10 }, + { "SCE_SQL_QOPERATOR", 24 }, + { "SCE_SQL_QUOTEDIDENTIFIER", 23 }, + { "SCE_SQL_SQLPLUS", 8 }, + { "SCE_SQL_SQLPLUS_COMMENT", 13 }, + { "SCE_SQL_SQLPLUS_PROMPT", 9 }, + { "SCE_SQL_STRING", 6 }, + { "SCE_SQL_USER1", 19 }, + { "SCE_SQL_USER2", 20 }, + { "SCE_SQL_USER3", 21 }, + { "SCE_SQL_USER4", 22 }, + { "SCE_SQL_WORD", 5 }, + { "SCE_SQL_WORD2", 16 }, + { "SCE_STATA_COMMENT", 1 }, + { "SCE_STATA_COMMENTBLOCK", 3 }, + { "SCE_STATA_COMMENTLINE", 2 }, + { "SCE_STATA_DEFAULT", 0 }, + { "SCE_STATA_GLOBAL_MACRO", 10 }, + { "SCE_STATA_IDENTIFIER", 6 }, + { "SCE_STATA_MACRO", 11 }, + { "SCE_STATA_NUMBER", 4 }, + { "SCE_STATA_OPERATOR", 5 }, + { "SCE_STATA_STRING", 7 }, + { "SCE_STATA_TYPE", 8 }, + { "SCE_STATA_WORD", 9 }, + { "SCE_STTXT_CHARACTER", 11 }, + { "SCE_STTXT_COMMENT", 1 }, + { "SCE_STTXT_COMMENTLINE", 2 }, + { "SCE_STTXT_DATETIME", 16 }, + { "SCE_STTXT_DEFAULT", 0 }, + { "SCE_STTXT_FB", 6 }, + { "SCE_STTXT_FUNCTION", 5 }, + { "SCE_STTXT_HEXNUMBER", 8 }, + { "SCE_STTXT_IDENTIFIER", 15 }, + { "SCE_STTXT_KEYWORD", 3 }, + { "SCE_STTXT_NUMBER", 7 }, + { "SCE_STTXT_OPERATOR", 10 }, + { "SCE_STTXT_PRAGMA", 9 }, + { "SCE_STTXT_PRAGMAS", 18 }, + { "SCE_STTXT_STRING1", 12 }, + { "SCE_STTXT_STRING2", 13 }, + { "SCE_STTXT_STRINGEOL", 14 }, + { "SCE_STTXT_TYPE", 4 }, + { "SCE_STTXT_VARS", 17 }, + { "SCE_ST_ASSIGN", 14 }, + { "SCE_ST_BINARY", 5 }, + { "SCE_ST_BOOL", 6 }, + { "SCE_ST_CHARACTER", 15 }, + { "SCE_ST_COMMENT", 3 }, + { "SCE_ST_DEFAULT", 0 }, + { "SCE_ST_GLOBAL", 10 }, + { "SCE_ST_KWSEND", 13 }, + { "SCE_ST_NIL", 9 }, + { "SCE_ST_NUMBER", 2 }, + { "SCE_ST_RETURN", 11 }, + { "SCE_ST_SELF", 7 }, + { "SCE_ST_SPECIAL", 12 }, + { "SCE_ST_SPEC_SEL", 16 }, + { "SCE_ST_STRING", 1 }, + { "SCE_ST_SUPER", 8 }, + { "SCE_ST_SYMBOL", 4 }, + { "SCE_T3_BLOCK_COMMENT", 3 }, + { "SCE_T3_BRACE", 20 }, + { "SCE_T3_DEFAULT", 0 }, + { "SCE_T3_D_STRING", 10 }, + { "SCE_T3_HTML_DEFAULT", 15 }, + { "SCE_T3_HTML_STRING", 16 }, + { "SCE_T3_HTML_TAG", 14 }, + { "SCE_T3_IDENTIFIER", 8 }, + { "SCE_T3_KEYWORD", 6 }, + { "SCE_T3_LIB_DIRECTIVE", 12 }, + { "SCE_T3_LINE_COMMENT", 4 }, + { "SCE_T3_MSG_PARAM", 13 }, + { "SCE_T3_NUMBER", 7 }, + { "SCE_T3_OPERATOR", 5 }, + { "SCE_T3_PREPROCESSOR", 2 }, + { "SCE_T3_S_STRING", 9 }, + { "SCE_T3_USER1", 17 }, + { "SCE_T3_USER2", 18 }, + { "SCE_T3_USER3", 19 }, + { "SCE_T3_X_DEFAULT", 1 }, + { "SCE_T3_X_STRING", 11 }, + { "SCE_TCL_BLOCK_COMMENT", 21 }, + { "SCE_TCL_COMMENT", 1 }, + { "SCE_TCL_COMMENTLINE", 2 }, + { "SCE_TCL_COMMENT_BOX", 20 }, + { "SCE_TCL_DEFAULT", 0 }, + { "SCE_TCL_EXPAND", 11 }, + { "SCE_TCL_IDENTIFIER", 7 }, + { "SCE_TCL_IN_QUOTE", 5 }, + { "SCE_TCL_MODIFIER", 10 }, + { "SCE_TCL_NUMBER", 3 }, + { "SCE_TCL_OPERATOR", 6 }, + { "SCE_TCL_SUBSTITUTION", 8 }, + { "SCE_TCL_SUB_BRACE", 9 }, + { "SCE_TCL_WORD", 12 }, + { "SCE_TCL_WORD2", 13 }, + { "SCE_TCL_WORD3", 14 }, + { "SCE_TCL_WORD4", 15 }, + { "SCE_TCL_WORD5", 16 }, + { "SCE_TCL_WORD6", 17 }, + { "SCE_TCL_WORD7", 18 }, + { "SCE_TCL_WORD8", 19 }, + { "SCE_TCL_WORD_IN_QUOTE", 4 }, + { "SCE_TCMD_CLABEL", 10 }, + { "SCE_TCMD_COMMAND", 5 }, + { "SCE_TCMD_COMMENT", 1 }, + { "SCE_TCMD_DEFAULT", 0 }, + { "SCE_TCMD_ENVIRONMENT", 8 }, + { "SCE_TCMD_EXPANSION", 9 }, + { "SCE_TCMD_HIDE", 4 }, + { "SCE_TCMD_IDENTIFIER", 6 }, + { "SCE_TCMD_LABEL", 3 }, + { "SCE_TCMD_OPERATOR", 7 }, + { "SCE_TCMD_WORD", 2 }, + { "SCE_TEX_COMMAND", 4 }, + { "SCE_TEX_DEFAULT", 0 }, + { "SCE_TEX_GROUP", 2 }, + { "SCE_TEX_SPECIAL", 1 }, + { "SCE_TEX_SYMBOL", 3 }, + { "SCE_TEX_TEXT", 5 }, + { "SCE_TXT2TAGS_BLOCKQUOTE", 15 }, + { "SCE_TXT2TAGS_CODE", 19 }, + { "SCE_TXT2TAGS_CODE2", 20 }, + { "SCE_TXT2TAGS_CODEBK", 21 }, + { "SCE_TXT2TAGS_COMMENT", 22 }, + { "SCE_TXT2TAGS_DEFAULT", 0 }, + { "SCE_TXT2TAGS_EM1", 4 }, + { "SCE_TXT2TAGS_EM2", 5 }, + { "SCE_TXT2TAGS_HEADER1", 6 }, + { "SCE_TXT2TAGS_HEADER2", 7 }, + { "SCE_TXT2TAGS_HEADER3", 8 }, + { "SCE_TXT2TAGS_HEADER4", 9 }, + { "SCE_TXT2TAGS_HEADER5", 10 }, + { "SCE_TXT2TAGS_HEADER6", 11 }, + { "SCE_TXT2TAGS_HRULE", 17 }, + { "SCE_TXT2TAGS_LINE_BEGIN", 1 }, + { "SCE_TXT2TAGS_LINK", 18 }, + { "SCE_TXT2TAGS_OLIST_ITEM", 14 }, + { "SCE_TXT2TAGS_OPTION", 23 }, + { "SCE_TXT2TAGS_POSTPROC", 25 }, + { "SCE_TXT2TAGS_PRECHAR", 12 }, + { "SCE_TXT2TAGS_PREPROC", 24 }, + { "SCE_TXT2TAGS_STRIKEOUT", 16 }, + { "SCE_TXT2TAGS_STRONG1", 2 }, + { "SCE_TXT2TAGS_STRONG2", 3 }, + { "SCE_TXT2TAGS_ULIST_ITEM", 13 }, + { "SCE_VHDL_ATTRIBUTE", 10 }, + { "SCE_VHDL_BLOCK_COMMENT", 15 }, + { "SCE_VHDL_COMMENT", 1 }, + { "SCE_VHDL_COMMENTLINEBANG", 2 }, + { "SCE_VHDL_DEFAULT", 0 }, + { "SCE_VHDL_IDENTIFIER", 6 }, + { "SCE_VHDL_KEYWORD", 8 }, + { "SCE_VHDL_NUMBER", 3 }, + { "SCE_VHDL_OPERATOR", 5 }, + { "SCE_VHDL_STDFUNCTION", 11 }, + { "SCE_VHDL_STDOPERATOR", 9 }, + { "SCE_VHDL_STDPACKAGE", 12 }, + { "SCE_VHDL_STDTYPE", 13 }, + { "SCE_VHDL_STRING", 4 }, + { "SCE_VHDL_STRINGEOL", 7 }, + { "SCE_VHDL_USERWORD", 14 }, + { "SCE_VISUALPROLOG_ANONYMOUS", 10 }, + { "SCE_VISUALPROLOG_CHARACTER", 13 }, + { "SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR", 15 }, + { "SCE_VISUALPROLOG_CHARACTER_TOO_MANY", 14 }, + { "SCE_VISUALPROLOG_COMMENT_BLOCK", 4 }, + { "SCE_VISUALPROLOG_COMMENT_KEY", 6 }, + { "SCE_VISUALPROLOG_COMMENT_KEY_ERROR", 7 }, + { "SCE_VISUALPROLOG_COMMENT_LINE", 5 }, + { "SCE_VISUALPROLOG_DEFAULT", 0 }, + { "SCE_VISUALPROLOG_IDENTIFIER", 8 }, + { "SCE_VISUALPROLOG_KEY_DIRECTIVE", 3 }, + { "SCE_VISUALPROLOG_KEY_MAJOR", 1 }, + { "SCE_VISUALPROLOG_KEY_MINOR", 2 }, + { "SCE_VISUALPROLOG_NUMBER", 11 }, + { "SCE_VISUALPROLOG_OPERATOR", 12 }, + { "SCE_VISUALPROLOG_STRING", 16 }, + { "SCE_VISUALPROLOG_STRING_EOL_OPEN", 19 }, + { "SCE_VISUALPROLOG_STRING_ESCAPE", 17 }, + { "SCE_VISUALPROLOG_STRING_ESCAPE_ERROR", 18 }, + { "SCE_VISUALPROLOG_STRING_VERBATIM", 20 }, + { "SCE_VISUALPROLOG_STRING_VERBATIM_EOL", 22 }, + { "SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL", 21 }, + { "SCE_VISUALPROLOG_VARIABLE", 9 }, + { "SCE_V_COMMENT", 1 }, + { "SCE_V_COMMENTLINE", 2 }, + { "SCE_V_COMMENTLINEBANG", 3 }, + { "SCE_V_COMMENT_WORD", 20 }, + { "SCE_V_DEFAULT", 0 }, + { "SCE_V_IDENTIFIER", 11 }, + { "SCE_V_INOUT", 23 }, + { "SCE_V_INPUT", 21 }, + { "SCE_V_NUMBER", 4 }, + { "SCE_V_OPERATOR", 10 }, + { "SCE_V_OUTPUT", 22 }, + { "SCE_V_PORT_CONNECT", 24 }, + { "SCE_V_PREPROCESSOR", 9 }, + { "SCE_V_STRING", 6 }, + { "SCE_V_STRINGEOL", 12 }, + { "SCE_V_USER", 19 }, + { "SCE_V_WORD", 5 }, + { "SCE_V_WORD2", 7 }, + { "SCE_V_WORD3", 8 }, + { "SCE_YAML_COMMENT", 1 }, + { "SCE_YAML_DEFAULT", 0 }, + { "SCE_YAML_DOCUMENT", 6 }, + { "SCE_YAML_ERROR", 8 }, + { "SCE_YAML_IDENTIFIER", 2 }, + { "SCE_YAML_KEYWORD", 3 }, + { "SCE_YAML_NUMBER", 4 }, + { "SCE_YAML_OPERATOR", 9 }, + { "SCE_YAML_REFERENCE", 5 }, + { "SCE_YAML_TEXT", 7 }, + { "SCFIND_CXX11REGEX", 0x00800000 }, + { "SCFIND_MATCHCASE", 0x4 }, + { "SCFIND_POSIX", 0x00400000 }, + { "SCFIND_REGEXP", 0x00200000 }, + { "SCFIND_WHOLEWORD", 0x2 }, + { "SCFIND_WORDSTART", 0x00100000 }, + { "SCI_ANNOTATIONGETLINES", 2546 }, + { "SCI_ANNOTATIONGETSTYLE", 2543 }, + { "SCI_ANNOTATIONGETSTYLEOFFSET", 2551 }, + { "SCI_ANNOTATIONGETSTYLES", 2545 }, + { "SCI_ANNOTATIONGETTEXT", 2541 }, + { "SCI_ANNOTATIONGETVISIBLE", 2549 }, + { "SCI_ANNOTATIONSETSTYLE", 2542 }, + { "SCI_ANNOTATIONSETSTYLEOFFSET", 2550 }, + { "SCI_ANNOTATIONSETSTYLES", 2544 }, + { "SCI_ANNOTATIONSETTEXT", 2540 }, + { "SCI_ANNOTATIONSETVISIBLE", 2548 }, + { "SCI_AUTOCGETAUTOHIDE", 2119 }, + { "SCI_AUTOCGETCANCELATSTART", 2111 }, + { "SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR", 2635 }, + { "SCI_AUTOCGETCHOOSESINGLE", 2114 }, + { "SCI_AUTOCGETCURRENT", 2445 }, + { "SCI_AUTOCGETCURRENTTEXT", 2610 }, + { "SCI_AUTOCGETDROPRESTOFWORD", 2271 }, + { "SCI_AUTOCGETIGNORECASE", 2116 }, + { "SCI_AUTOCGETMAXHEIGHT", 2211 }, + { "SCI_AUTOCGETMAXWIDTH", 2209 }, + { "SCI_AUTOCGETMULTI", 2637 }, + { "SCI_AUTOCGETORDER", 2661 }, + { "SCI_AUTOCGETSEPARATOR", 2107 }, + { "SCI_AUTOCGETTYPESEPARATOR", 2285 }, + { "SCI_AUTOCSETAUTOHIDE", 2118 }, + { "SCI_AUTOCSETCANCELATSTART", 2110 }, + { "SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR", 2634 }, + { "SCI_AUTOCSETCHOOSESINGLE", 2113 }, + { "SCI_AUTOCSETDROPRESTOFWORD", 2270 }, + { "SCI_AUTOCSETFILLUPS", 2112 }, + { "SCI_AUTOCSETIGNORECASE", 2115 }, + { "SCI_AUTOCSETMAXHEIGHT", 2210 }, + { "SCI_AUTOCSETMAXWIDTH", 2208 }, + { "SCI_AUTOCSETMULTI", 2636 }, + { "SCI_AUTOCSETORDER", 2660 }, + { "SCI_AUTOCSETSEPARATOR", 2106 }, + { "SCI_AUTOCSETTYPESEPARATOR", 2286 }, + { "SCI_CALLTIPSETBACK", 2205 }, + { "SCI_CALLTIPSETFORE", 2206 }, + { "SCI_CALLTIPSETFOREHLT", 2207 }, + { "SCI_CALLTIPSETPOSITION", 2213 }, + { "SCI_CALLTIPSETPOSSTART", 2214 }, + { "SCI_CALLTIPUSESTYLE", 2212 }, + { "SCI_DISTANCETOSECONDARYSTYLES", 4025 }, + { "SCI_FOLDDISPLAYTEXTSETSTYLE", 2701 }, + { "SCI_GETACCESSIBILITY", 2703 }, + { "SCI_GETADDITIONALCARETFORE", 2605 }, + { "SCI_GETADDITIONALCARETSBLINK", 2568 }, + { "SCI_GETADDITIONALCARETSVISIBLE", 2609 }, + { "SCI_GETADDITIONALSELALPHA", 2603 }, + { "SCI_GETADDITIONALSELECTIONTYPING", 2566 }, + { "SCI_GETALLLINESVISIBLE", 2236 }, + { "SCI_GETANCHOR", 2009 }, + { "SCI_GETAUTOMATICFOLD", 2664 }, + { "SCI_GETBACKSPACEUNINDENTS", 2263 }, + { "SCI_GETBIDIRECTIONAL", 2708 }, + { "SCI_GETBUFFEREDDRAW", 2034 }, + { "SCI_GETCARETFORE", 2138 }, + { "SCI_GETCARETLINEBACK", 2097 }, + { "SCI_GETCARETLINEBACKALPHA", 2471 }, + { "SCI_GETCARETLINEFRAME", 2704 }, + { "SCI_GETCARETLINEVISIBLE", 2095 }, + { "SCI_GETCARETLINEVISIBLEALWAYS", 2654 }, + { "SCI_GETCARETPERIOD", 2075 }, + { "SCI_GETCARETSTICKY", 2457 }, + { "SCI_GETCARETSTYLE", 2513 }, + { "SCI_GETCARETWIDTH", 2189 }, + { "SCI_GETCHARACTERPOINTER", 2520 }, + { "SCI_GETCHARAT", 2007 }, + { "SCI_GETCODEPAGE", 2137 }, + { "SCI_GETCOLUMN", 2129 }, + { "SCI_GETCOMMANDEVENTS", 2718 }, + { "SCI_GETCONTROLCHARSYMBOL", 2389 }, + { "SCI_GETCURRENTPOS", 2008 }, + { "SCI_GETCURSOR", 2387 }, + { "SCI_GETDIRECTFUNCTION", 2184 }, + { "SCI_GETDIRECTPOINTER", 2185 }, + { "SCI_GETDOCPOINTER", 2357 }, + { "SCI_GETDOCUMENTOPTIONS", 2379 }, + { "SCI_GETEDGECOLOUR", 2364 }, + { "SCI_GETEDGECOLUMN", 2360 }, + { "SCI_GETEDGEMODE", 2362 }, + { "SCI_GETENDATLASTLINE", 2278 }, + { "SCI_GETENDSTYLED", 2028 }, + { "SCI_GETEOLMODE", 2030 }, + { "SCI_GETEXTRAASCENT", 2526 }, + { "SCI_GETEXTRADESCENT", 2528 }, + { "SCI_GETFIRSTVISIBLELINE", 2152 }, + { "SCI_GETFOCUS", 2381 }, + { "SCI_GETFOLDEXPANDED", 2230 }, + { "SCI_GETFOLDLEVEL", 2223 }, + { "SCI_GETFOLDPARENT", 2225 }, + { "SCI_GETFONTQUALITY", 2612 }, + { "SCI_GETGAPPOSITION", 2644 }, + { "SCI_GETHIGHLIGHTGUIDE", 2135 }, + { "SCI_GETHOTSPOTACTIVEUNDERLINE", 2496 }, + { "SCI_GETHOTSPOTSINGLELINE", 2497 }, + { "SCI_GETHSCROLLBAR", 2131 }, + { "SCI_GETIDENTIFIER", 2623 }, + { "SCI_GETIDLESTYLING", 2693 }, + { "SCI_GETIMEINTERACTION", 2678 }, + { "SCI_GETINDENT", 2123 }, + { "SCI_GETINDENTATIONGUIDES", 2133 }, + { "SCI_GETINDICATORCURRENT", 2501 }, + { "SCI_GETINDICATORVALUE", 2503 }, + { "SCI_GETLAYOUTCACHE", 2273 }, + { "SCI_GETLENGTH", 2006 }, + { "SCI_GETLEXER", 4002 }, + { "SCI_GETLEXERLANGUAGE", 4012 }, + { "SCI_GETLINECHARACTERINDEX", 2710 }, + { "SCI_GETLINECOUNT", 2154 }, + { "SCI_GETLINEENDPOSITION", 2136 }, + { "SCI_GETLINEENDTYPESACTIVE", 2658 }, + { "SCI_GETLINEENDTYPESALLOWED", 2657 }, + { "SCI_GETLINEENDTYPESSUPPORTED", 4018 }, + { "SCI_GETLINEINDENTATION", 2127 }, + { "SCI_GETLINEINDENTPOSITION", 2128 }, + { "SCI_GETLINESTATE", 2093 }, + { "SCI_GETLINEVISIBLE", 2228 }, + { "SCI_GETMAINSELECTION", 2575 }, + { "SCI_GETMARGINBACKN", 2251 }, + { "SCI_GETMARGINCURSORN", 2249 }, + { "SCI_GETMARGINLEFT", 2156 }, + { "SCI_GETMARGINMASKN", 2245 }, + { "SCI_GETMARGINOPTIONS", 2557 }, + { "SCI_GETMARGINRIGHT", 2158 }, + { "SCI_GETMARGINS", 2253 }, + { "SCI_GETMARGINSENSITIVEN", 2247 }, + { "SCI_GETMARGINTYPEN", 2241 }, + { "SCI_GETMARGINWIDTHN", 2243 }, + { "SCI_GETMAXLINESTATE", 2094 }, + { "SCI_GETMODEVENTMASK", 2378 }, + { "SCI_GETMODIFY", 2159 }, + { "SCI_GETMOUSEDOWNCAPTURES", 2385 }, + { "SCI_GETMOUSEDWELLTIME", 2265 }, + { "SCI_GETMOUSESELECTIONRECTANGULARSWITCH", 2669 }, + { "SCI_GETMOUSEWHEELCAPTURES", 2697 }, + { "SCI_GETMOVEEXTENDSSELECTION", 2706 }, + { "SCI_GETMULTIPASTE", 2615 }, + { "SCI_GETMULTIPLESELECTION", 2564 }, + { "SCI_GETNAMEDSTYLES", 4029 }, + { "SCI_GETOVERTYPE", 2187 }, + { "SCI_GETPASTECONVERTENDINGS", 2468 }, + { "SCI_GETPHASESDRAW", 2673 }, + { "SCI_GETPOSITIONCACHE", 2515 }, + { "SCI_GETPRIMARYSTYLEFROMSTYLE", 4028 }, + { "SCI_GETPRINTCOLOURMODE", 2149 }, + { "SCI_GETPRINTMAGNIFICATION", 2147 }, + { "SCI_GETPRINTWRAPMODE", 2407 }, + { "SCI_GETPROPERTY", 4008 }, + { "SCI_GETPROPERTYEXPANDED", 4009 }, + { "SCI_GETPUNCTUATIONCHARS", 2649 }, + { "SCI_GETREADONLY", 2140 }, + { "SCI_GETRECTANGULARSELECTIONANCHOR", 2591 }, + { "SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE", 2595 }, + { "SCI_GETRECTANGULARSELECTIONCARET", 2589 }, + { "SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE", 2593 }, + { "SCI_GETRECTANGULARSELECTIONMODIFIER", 2599 }, + { "SCI_GETREPRESENTATION", 2666 }, + { "SCI_GETSCROLLWIDTH", 2275 }, + { "SCI_GETSCROLLWIDTHTRACKING", 2517 }, + { "SCI_GETSEARCHFLAGS", 2199 }, + { "SCI_GETSELALPHA", 2477 }, + { "SCI_GETSELECTIONEMPTY", 2650 }, + { "SCI_GETSELECTIONEND", 2145 }, + { "SCI_GETSELECTIONMODE", 2423 }, + { "SCI_GETSELECTIONNANCHOR", 2579 }, + { "SCI_GETSELECTIONNANCHORVIRTUALSPACE", 2583 }, + { "SCI_GETSELECTIONNCARET", 2577 }, + { "SCI_GETSELECTIONNCARETVIRTUALSPACE", 2581 }, + { "SCI_GETSELECTIONNEND", 2587 }, + { "SCI_GETSELECTIONNSTART", 2585 }, + { "SCI_GETSELECTIONS", 2570 }, + { "SCI_GETSELECTIONSTART", 2143 }, + { "SCI_GETSELEOLFILLED", 2479 }, + { "SCI_GETSTATUS", 2383 }, + { "SCI_GETSTYLEAT", 2010 }, + { "SCI_GETSTYLEFROMSUBSTYLE", 4027 }, + { "SCI_GETSUBSTYLEBASES", 4026 }, + { "SCI_GETSUBSTYLESLENGTH", 4022 }, + { "SCI_GETSUBSTYLESSTART", 4021 }, + { "SCI_GETTABDRAWMODE", 2698 }, + { "SCI_GETTABINDENTS", 2261 }, + { "SCI_GETTABWIDTH", 2121 }, + { "SCI_GETTAG", 2616 }, + { "SCI_GETTARGETEND", 2193 }, + { "SCI_GETTARGETSTART", 2191 }, + { "SCI_GETTARGETTEXT", 2687 }, + { "SCI_GETTECHNOLOGY", 2631 }, + { "SCI_GETTEXTLENGTH", 2183 }, + { "SCI_GETUNDOCOLLECTION", 2019 }, + { "SCI_GETUSETABS", 2125 }, + { "SCI_GETVIEWEOL", 2355 }, + { "SCI_GETVIEWWS", 2020 }, + { "SCI_GETVIRTUALSPACEOPTIONS", 2597 }, + { "SCI_GETVSCROLLBAR", 2281 }, + { "SCI_GETWHITESPACECHARS", 2647 }, + { "SCI_GETWHITESPACESIZE", 2087 }, + { "SCI_GETWORDCHARS", 2646 }, + { "SCI_GETWRAPINDENTMODE", 2473 }, + { "SCI_GETWRAPMODE", 2269 }, + { "SCI_GETWRAPSTARTINDENT", 2465 }, + { "SCI_GETWRAPVISUALFLAGS", 2461 }, + { "SCI_GETWRAPVISUALFLAGSLOCATION", 2463 }, + { "SCI_GETXOFFSET", 2398 }, + { "SCI_GETZOOM", 2374 }, + { "SCI_INDICGETALPHA", 2524 }, + { "SCI_INDICGETFLAGS", 2685 }, + { "SCI_INDICGETFORE", 2083 }, + { "SCI_INDICGETHOVERFORE", 2683 }, + { "SCI_INDICGETHOVERSTYLE", 2681 }, + { "SCI_INDICGETOUTLINEALPHA", 2559 }, + { "SCI_INDICGETSTYLE", 2081 }, + { "SCI_INDICGETUNDER", 2511 }, + { "SCI_INDICSETALPHA", 2523 }, + { "SCI_INDICSETFLAGS", 2684 }, + { "SCI_INDICSETFORE", 2082 }, + { "SCI_INDICSETHOVERFORE", 2682 }, + { "SCI_INDICSETHOVERSTYLE", 2680 }, + { "SCI_INDICSETOUTLINEALPHA", 2558 }, + { "SCI_INDICSETSTYLE", 2080 }, + { "SCI_INDICSETUNDER", 2510 }, + { "SCI_LEXER_START", 4000 }, + { "SCI_LINESONSCREEN", 2370 }, + { "SCI_MARGINGETSTYLE", 2533 }, + { "SCI_MARGINGETSTYLEOFFSET", 2538 }, + { "SCI_MARGINGETSTYLES", 2535 }, + { "SCI_MARGINGETTEXT", 2531 }, + { "SCI_MARGINSETSTYLE", 2532 }, + { "SCI_MARGINSETSTYLEOFFSET", 2537 }, + { "SCI_MARGINSETSTYLES", 2534 }, + { "SCI_MARGINSETTEXT", 2530 }, + { "SCI_MARKERSETALPHA", 2476 }, + { "SCI_MARKERSETBACK", 2042 }, + { "SCI_MARKERSETBACKSELECTED", 2292 }, + { "SCI_MARKERSETFORE", 2041 }, + { "SCI_OPTIONAL_START", 3000 }, + { "SCI_RGBAIMAGESETHEIGHT", 2625 }, + { "SCI_RGBAIMAGESETSCALE", 2651 }, + { "SCI_RGBAIMAGESETWIDTH", 2624 }, + { "SCI_SELECTIONISRECTANGLE", 2372 }, + { "SCI_SETACCESSIBILITY", 2702 }, + { "SCI_SETADDITIONALCARETFORE", 2604 }, + { "SCI_SETADDITIONALCARETSBLINK", 2567 }, + { "SCI_SETADDITIONALCARETSVISIBLE", 2608 }, + { "SCI_SETADDITIONALSELALPHA", 2602 }, + { "SCI_SETADDITIONALSELBACK", 2601 }, + { "SCI_SETADDITIONALSELECTIONTYPING", 2565 }, + { "SCI_SETADDITIONALSELFORE", 2600 }, + { "SCI_SETANCHOR", 2026 }, + { "SCI_SETAUTOMATICFOLD", 2663 }, + { "SCI_SETBACKSPACEUNINDENTS", 2262 }, + { "SCI_SETBIDIRECTIONAL", 2709 }, + { "SCI_SETBUFFEREDDRAW", 2035 }, + { "SCI_SETCARETFORE", 2069 }, + { "SCI_SETCARETLINEBACK", 2098 }, + { "SCI_SETCARETLINEBACKALPHA", 2470 }, + { "SCI_SETCARETLINEFRAME", 2705 }, + { "SCI_SETCARETLINEVISIBLE", 2096 }, + { "SCI_SETCARETLINEVISIBLEALWAYS", 2655 }, + { "SCI_SETCARETPERIOD", 2076 }, + { "SCI_SETCARETSTICKY", 2458 }, + { "SCI_SETCARETSTYLE", 2512 }, + { "SCI_SETCARETWIDTH", 2188 }, + { "SCI_SETCODEPAGE", 2037 }, + { "SCI_SETCOMMANDEVENTS", 2717 }, + { "SCI_SETCONTROLCHARSYMBOL", 2388 }, + { "SCI_SETCURRENTPOS", 2141 }, + { "SCI_SETCURSOR", 2386 }, + { "SCI_SETDOCPOINTER", 2358 }, + { "SCI_SETEDGECOLOUR", 2365 }, + { "SCI_SETEDGECOLUMN", 2361 }, + { "SCI_SETEDGEMODE", 2363 }, + { "SCI_SETENDATLASTLINE", 2277 }, + { "SCI_SETEOLMODE", 2031 }, + { "SCI_SETEXTRAASCENT", 2525 }, + { "SCI_SETEXTRADESCENT", 2527 }, + { "SCI_SETFIRSTVISIBLELINE", 2613 }, + { "SCI_SETFOCUS", 2380 }, + { "SCI_SETFOLDEXPANDED", 2229 }, + { "SCI_SETFOLDFLAGS", 2233 }, + { "SCI_SETFOLDLEVEL", 2222 }, + { "SCI_SETFONTQUALITY", 2611 }, + { "SCI_SETHIGHLIGHTGUIDE", 2134 }, + { "SCI_SETHOTSPOTACTIVEUNDERLINE", 2412 }, + { "SCI_SETHOTSPOTSINGLELINE", 2421 }, + { "SCI_SETHSCROLLBAR", 2130 }, + { "SCI_SETIDENTIFIER", 2622 }, + { "SCI_SETIDENTIFIERS", 4024 }, + { "SCI_SETIDLESTYLING", 2692 }, + { "SCI_SETIMEINTERACTION", 2679 }, + { "SCI_SETINDENT", 2122 }, + { "SCI_SETINDENTATIONGUIDES", 2132 }, + { "SCI_SETINDICATORCURRENT", 2500 }, + { "SCI_SETINDICATORVALUE", 2502 }, + { "SCI_SETKEYWORDS", 4005 }, + { "SCI_SETLAYOUTCACHE", 2272 }, + { "SCI_SETLEXER", 4001 }, + { "SCI_SETLEXERLANGUAGE", 4006 }, + { "SCI_SETLINEENDTYPESALLOWED", 2656 }, + { "SCI_SETLINEINDENTATION", 2126 }, + { "SCI_SETLINESTATE", 2092 }, + { "SCI_SETMAINSELECTION", 2574 }, + { "SCI_SETMARGINBACKN", 2250 }, + { "SCI_SETMARGINCURSORN", 2248 }, + { "SCI_SETMARGINLEFT", 2155 }, + { "SCI_SETMARGINMASKN", 2244 }, + { "SCI_SETMARGINOPTIONS", 2539 }, + { "SCI_SETMARGINRIGHT", 2157 }, + { "SCI_SETMARGINS", 2252 }, + { "SCI_SETMARGINSENSITIVEN", 2246 }, + { "SCI_SETMARGINTYPEN", 2240 }, + { "SCI_SETMARGINWIDTHN", 2242 }, + { "SCI_SETMODEVENTMASK", 2359 }, + { "SCI_SETMOUSEDOWNCAPTURES", 2384 }, + { "SCI_SETMOUSEDWELLTIME", 2264 }, + { "SCI_SETMOUSESELECTIONRECTANGULARSWITCH", 2668 }, + { "SCI_SETMOUSEWHEELCAPTURES", 2696 }, + { "SCI_SETMULTIPASTE", 2614 }, + { "SCI_SETMULTIPLESELECTION", 2563 }, + { "SCI_SETOVERTYPE", 2186 }, + { "SCI_SETPASTECONVERTENDINGS", 2467 }, + { "SCI_SETPHASESDRAW", 2674 }, + { "SCI_SETPOSITIONCACHE", 2514 }, + { "SCI_SETPRINTCOLOURMODE", 2148 }, + { "SCI_SETPRINTMAGNIFICATION", 2146 }, + { "SCI_SETPRINTWRAPMODE", 2406 }, + { "SCI_SETPROPERTY", 4004 }, + { "SCI_SETPUNCTUATIONCHARS", 2648 }, + { "SCI_SETREADONLY", 2171 }, + { "SCI_SETRECTANGULARSELECTIONANCHOR", 2590 }, + { "SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE", 2594 }, + { "SCI_SETRECTANGULARSELECTIONCARET", 2588 }, + { "SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE", 2592 }, + { "SCI_SETRECTANGULARSELECTIONMODIFIER", 2598 }, + { "SCI_SETREPRESENTATION", 2665 }, + { "SCI_SETSCROLLWIDTH", 2274 }, + { "SCI_SETSCROLLWIDTHTRACKING", 2516 }, + { "SCI_SETSEARCHFLAGS", 2198 }, + { "SCI_SETSELALPHA", 2478 }, + { "SCI_SETSELECTIONEND", 2144 }, + { "SCI_SETSELECTIONMODE", 2422 }, + { "SCI_SETSELECTIONNANCHOR", 2578 }, + { "SCI_SETSELECTIONNANCHORVIRTUALSPACE", 2582 }, + { "SCI_SETSELECTIONNCARET", 2576 }, + { "SCI_SETSELECTIONNCARETVIRTUALSPACE", 2580 }, + { "SCI_SETSELECTIONNEND", 2586 }, + { "SCI_SETSELECTIONNSTART", 2584 }, + { "SCI_SETSELECTIONSTART", 2142 }, + { "SCI_SETSELEOLFILLED", 2480 }, + { "SCI_SETSTATUS", 2382 }, + { "SCI_SETTABDRAWMODE", 2699 }, + { "SCI_SETTABINDENTS", 2260 }, + { "SCI_SETTABWIDTH", 2036 }, + { "SCI_SETTARGETEND", 2192 }, + { "SCI_SETTARGETSTART", 2190 }, + { "SCI_SETTECHNOLOGY", 2630 }, + { "SCI_SETUNDOCOLLECTION", 2012 }, + { "SCI_SETUSETABS", 2124 }, + { "SCI_SETVIEWEOL", 2356 }, + { "SCI_SETVIEWWS", 2021 }, + { "SCI_SETVIRTUALSPACEOPTIONS", 2596 }, + { "SCI_SETVSCROLLBAR", 2280 }, + { "SCI_SETWHITESPACECHARS", 2443 }, + { "SCI_SETWHITESPACESIZE", 2086 }, + { "SCI_SETWORDCHARS", 2077 }, + { "SCI_SETWRAPINDENTMODE", 2472 }, + { "SCI_SETWRAPMODE", 2268 }, + { "SCI_SETWRAPSTARTINDENT", 2464 }, + { "SCI_SETWRAPVISUALFLAGS", 2460 }, + { "SCI_SETWRAPVISUALFLAGSLOCATION", 2462 }, + { "SCI_SETXOFFSET", 2397 }, + { "SCI_SETZOOM", 2373 }, + { "SCI_START", 2000 }, + { "SCI_STYLEGETBACK", 2482 }, + { "SCI_STYLEGETBOLD", 2483 }, + { "SCI_STYLEGETCASE", 2489 }, + { "SCI_STYLEGETCHANGEABLE", 2492 }, + { "SCI_STYLEGETCHARACTERSET", 2490 }, + { "SCI_STYLEGETEOLFILLED", 2487 }, + { "SCI_STYLEGETFONT", 2486 }, + { "SCI_STYLEGETFORE", 2481 }, + { "SCI_STYLEGETHOTSPOT", 2493 }, + { "SCI_STYLEGETITALIC", 2484 }, + { "SCI_STYLEGETSIZE", 2485 }, + { "SCI_STYLEGETSIZEFRACTIONAL", 2062 }, + { "SCI_STYLEGETUNDERLINE", 2488 }, + { "SCI_STYLEGETVISIBLE", 2491 }, + { "SCI_STYLEGETWEIGHT", 2064 }, + { "SCI_STYLESETBACK", 2052 }, + { "SCI_STYLESETBOLD", 2053 }, + { "SCI_STYLESETCASE", 2060 }, + { "SCI_STYLESETCHANGEABLE", 2099 }, + { "SCI_STYLESETCHARACTERSET", 2066 }, + { "SCI_STYLESETEOLFILLED", 2057 }, + { "SCI_STYLESETFONT", 2056 }, + { "SCI_STYLESETFORE", 2051 }, + { "SCI_STYLESETHOTSPOT", 2409 }, + { "SCI_STYLESETITALIC", 2054 }, + { "SCI_STYLESETSIZE", 2055 }, + { "SCI_STYLESETSIZEFRACTIONAL", 2061 }, + { "SCI_STYLESETUNDERLINE", 2059 }, + { "SCI_STYLESETVISIBLE", 2074 }, + { "SCI_STYLESETWEIGHT", 2063 }, + { "SCK_ADD", 310 }, + { "SCK_BACK", 8 }, + { "SCK_DELETE", 308 }, + { "SCK_DIVIDE", 312 }, + { "SCK_DOWN", 300 }, + { "SCK_END", 305 }, + { "SCK_ESCAPE", 7 }, + { "SCK_HOME", 304 }, + { "SCK_INSERT", 309 }, + { "SCK_LEFT", 302 }, + { "SCK_MENU", 315 }, + { "SCK_NEXT", 307 }, + { "SCK_PRIOR", 306 }, + { "SCK_RETURN", 13 }, + { "SCK_RIGHT", 303 }, + { "SCK_RWIN", 314 }, + { "SCK_SUBTRACT", 311 }, + { "SCK_TAB", 9 }, + { "SCK_UP", 301 }, + { "SCK_WIN", 313 }, + { "SCLEX_A68K", 100 }, + { "SCLEX_ABAQUS", 84 }, + { "SCLEX_ADA", 20 }, + { "SCLEX_APDL", 61 }, + { "SCLEX_AS", 113 }, + { "SCLEX_ASM", 34 }, + { "SCLEX_ASN1", 63 }, + { "SCLEX_ASYMPTOTE", 85 }, + { "SCLEX_AU3", 60 }, + { "SCLEX_AUTOMATIC", 1000 }, + { "SCLEX_AVE", 19 }, + { "SCLEX_AVS", 104 }, + { "SCLEX_BAAN", 31 }, + { "SCLEX_BASH", 62 }, + { "SCLEX_BATCH", 12 }, + { "SCLEX_BIBTEX", 116 }, + { "SCLEX_BLITZBASIC", 66 }, + { "SCLEX_BULLANT", 27 }, + { "SCLEX_CAML", 65 }, + { "SCLEX_CIL", 127 }, + { "SCLEX_CLW", 45 }, + { "SCLEX_CLWNOCASE", 46 }, + { "SCLEX_CMAKE", 80 }, + { "SCLEX_COBOL", 92 }, + { "SCLEX_COFFEESCRIPT", 102 }, + { "SCLEX_CONF", 17 }, + { "SCLEX_CONTAINER", 0 }, + { "SCLEX_CPP", 3 }, + { "SCLEX_CPPNOCASE", 35 }, + { "SCLEX_CSOUND", 74 }, + { "SCLEX_CSS", 38 }, + { "SCLEX_D", 79 }, + { "SCLEX_DIFF", 16 }, + { "SCLEX_DMAP", 112 }, + { "SCLEX_DMIS", 114 }, + { "SCLEX_ECL", 105 }, + { "SCLEX_EDIFACT", 121 }, + { "SCLEX_EIFFEL", 23 }, + { "SCLEX_EIFFELKW", 24 }, + { "SCLEX_ERLANG", 53 }, + { "SCLEX_ERRORLIST", 10 }, + { "SCLEX_ESCRIPT", 41 }, + { "SCLEX_F77", 37 }, + { "SCLEX_FLAGSHIP", 73 }, + { "SCLEX_FORTH", 52 }, + { "SCLEX_FORTRAN", 36 }, + { "SCLEX_FREEBASIC", 75 }, + { "SCLEX_GAP", 81 }, + { "SCLEX_GUI4CLI", 58 }, + { "SCLEX_HASKELL", 68 }, + { "SCLEX_HTML", 4 }, + { "SCLEX_IHEX", 118 }, + { "SCLEX_INDENT", 122 }, + { "SCLEX_INNOSETUP", 76 }, + { "SCLEX_JSON", 120 }, + { "SCLEX_KIX", 57 }, + { "SCLEX_KVIRC", 110 }, + { "SCLEX_LATEX", 14 }, + { "SCLEX_LISP", 21 }, + { "SCLEX_LITERATEHASKELL", 108 }, + { "SCLEX_LOT", 47 }, + { "SCLEX_LOUT", 40 }, + { "SCLEX_LUA", 15 }, + { "SCLEX_MAGIK", 87 }, + { "SCLEX_MAKEFILE", 11 }, + { "SCLEX_MARKDOWN", 98 }, + { "SCLEX_MATLAB", 32 }, + { "SCLEX_MAXIMA", 123 }, + { "SCLEX_METAPOST", 50 }, + { "SCLEX_MMIXAL", 44 }, + { "SCLEX_MODULA", 101 }, + { "SCLEX_MSSQL", 55 }, + { "SCLEX_MYSQL", 89 }, + { "SCLEX_NIM", 126 }, + { "SCLEX_NIMROD", 96 }, + { "SCLEX_NNCRONTAB", 26 }, + { "SCLEX_NSIS", 43 }, + { "SCLEX_NULL", 1 }, + { "SCLEX_OCTAVE", 54 }, + { "SCLEX_OPAL", 77 }, + { "SCLEX_OSCRIPT", 106 }, + { "SCLEX_PASCAL", 18 }, + { "SCLEX_PERL", 6 }, + { "SCLEX_PHPSCRIPT", 69 }, + { "SCLEX_PLM", 82 }, + { "SCLEX_PO", 90 }, + { "SCLEX_POV", 39 }, + { "SCLEX_POWERBASIC", 51 }, + { "SCLEX_POWERPRO", 95 }, + { "SCLEX_POWERSHELL", 88 }, + { "SCLEX_PROGRESS", 83 }, + { "SCLEX_PROPERTIES", 9 }, + { "SCLEX_PS", 42 }, + { "SCLEX_PUREBASIC", 67 }, + { "SCLEX_PYTHON", 2 }, + { "SCLEX_R", 86 }, + { "SCLEX_REBOL", 71 }, + { "SCLEX_REGISTRY", 115 }, + { "SCLEX_RUBY", 22 }, + { "SCLEX_RUST", 111 }, + { "SCLEX_SAS", 125 }, + { "SCLEX_SCRIPTOL", 33 }, + { "SCLEX_SMALLTALK", 72 }, + { "SCLEX_SML", 97 }, + { "SCLEX_SORCUS", 94 }, + { "SCLEX_SPECMAN", 59 }, + { "SCLEX_SPICE", 78 }, + { "SCLEX_SQL", 7 }, + { "SCLEX_SREC", 117 }, + { "SCLEX_STATA", 124 }, + { "SCLEX_STTXT", 109 }, + { "SCLEX_TACL", 93 }, + { "SCLEX_TADS3", 70 }, + { "SCLEX_TAL", 91 }, + { "SCLEX_TCL", 25 }, + { "SCLEX_TCMD", 103 }, + { "SCLEX_TEHEX", 119 }, + { "SCLEX_TEX", 49 }, + { "SCLEX_TXT2TAGS", 99 }, + { "SCLEX_VB", 8 }, + { "SCLEX_VBSCRIPT", 28 }, + { "SCLEX_VERILOG", 56 }, + { "SCLEX_VHDL", 64 }, + { "SCLEX_VISUALPROLOG", 107 }, + { "SCLEX_XCODE", 13 }, + { "SCLEX_XML", 5 }, + { "SCLEX_YAML", 48 }, + { "SCMOD_ALT", 4 }, + { "SCMOD_CTRL", 2 }, + { "SCMOD_META", 16 }, + { "SCMOD_NORM", 0 }, + { "SCMOD_SHIFT", 1 }, + { "SCMOD_SUPER", 8 }, + { "SCTD_LONGARROW", 0 }, + { "SCTD_STRIKEOUT", 1 }, + { "SCVS_NONE", 0 }, + { "SCVS_NOWRAPLINESTART", 4 }, + { "SCVS_RECTANGULARSELECTION", 1 }, + { "SCVS_USERACCESSIBLE", 2 }, + { "SCWS_INVISIBLE", 0 }, + { "SCWS_VISIBLEAFTERINDENT", 2 }, + { "SCWS_VISIBLEALWAYS", 1 }, + { "SCWS_VISIBLEONLYININDENT", 3 }, + { "SC_ACCESSIBILITY_DISABLED", 0 }, + { "SC_ACCESSIBILITY_ENABLED", 1 }, + { "SC_AC_COMMAND", 5 }, + { "SC_AC_DOUBLECLICK", 2 }, + { "SC_AC_FILLUP", 1 }, + { "SC_AC_NEWLINE", 4 }, + { "SC_AC_TAB", 3 }, + { "SC_ALPHA_NOALPHA", 256 }, + { "SC_ALPHA_OPAQUE", 255 }, + { "SC_ALPHA_TRANSPARENT", 0 }, + { "SC_AUTOMATICFOLD_CHANGE", 0x0004 }, + { "SC_AUTOMATICFOLD_CLICK", 0x0002 }, + { "SC_AUTOMATICFOLD_SHOW", 0x0001 }, + { "SC_BIDIRECTIONAL_DISABLED", 0 }, + { "SC_BIDIRECTIONAL_L2R", 1 }, + { "SC_BIDIRECTIONAL_R2L", 2 }, + { "SC_CACHE_CARET", 1 }, + { "SC_CACHE_DOCUMENT", 3 }, + { "SC_CACHE_NONE", 0 }, + { "SC_CACHE_PAGE", 2 }, + { "SC_CARETSTICKY_OFF", 0 }, + { "SC_CARETSTICKY_ON", 1 }, + { "SC_CARETSTICKY_WHITESPACE", 2 }, + { "SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE", 1 }, + { "SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE", 0 }, + { "SC_CASE_CAMEL", 3 }, + { "SC_CASE_LOWER", 2 }, + { "SC_CASE_MIXED", 0 }, + { "SC_CASE_UPPER", 1 }, + { "SC_CHARSET_8859_15", 1000 }, + { "SC_CHARSET_ANSI", 0 }, + { "SC_CHARSET_ARABIC", 178 }, + { "SC_CHARSET_BALTIC", 186 }, + { "SC_CHARSET_CHINESEBIG5", 136 }, + { "SC_CHARSET_CYRILLIC", 1251 }, + { "SC_CHARSET_DEFAULT", 1 }, + { "SC_CHARSET_EASTEUROPE", 238 }, + { "SC_CHARSET_GB2312", 134 }, + { "SC_CHARSET_GREEK", 161 }, + { "SC_CHARSET_HANGUL", 129 }, + { "SC_CHARSET_HEBREW", 177 }, + { "SC_CHARSET_JOHAB", 130 }, + { "SC_CHARSET_MAC", 77 }, + { "SC_CHARSET_OEM", 255 }, + { "SC_CHARSET_OEM866", 866 }, + { "SC_CHARSET_RUSSIAN", 204 }, + { "SC_CHARSET_SHIFTJIS", 128 }, + { "SC_CHARSET_SYMBOL", 2 }, + { "SC_CHARSET_THAI", 222 }, + { "SC_CHARSET_TURKISH", 162 }, + { "SC_CHARSET_VIETNAMESE", 163 }, + { "SC_CP_UTF8", 65001 }, + { "SC_CURSORARROW", 2 }, + { "SC_CURSORNORMAL", -1 }, + { "SC_CURSORREVERSEARROW", 7 }, + { "SC_CURSORWAIT", 4 }, + { "SC_DOCUMENTOPTION_DEFAULT", 0 }, + { "SC_DOCUMENTOPTION_STYLES_NONE", 0x1 }, + { "SC_DOCUMENTOPTION_TEXT_LARGE", 0x100 }, + { "SC_EFF_QUALITY_ANTIALIASED", 2 }, + { "SC_EFF_QUALITY_DEFAULT", 0 }, + { "SC_EFF_QUALITY_LCD_OPTIMIZED", 3 }, + { "SC_EFF_QUALITY_MASK", 0xF }, + { "SC_EFF_QUALITY_NON_ANTIALIASED", 1 }, + { "SC_EOL_CR", 1 }, + { "SC_EOL_CRLF", 0 }, + { "SC_EOL_LF", 2 }, + { "SC_FOLDACTION_CONTRACT", 0 }, + { "SC_FOLDACTION_EXPAND", 1 }, + { "SC_FOLDACTION_TOGGLE", 2 }, + { "SC_FOLDDISPLAYTEXT_BOXED", 2 }, + { "SC_FOLDDISPLAYTEXT_HIDDEN", 0 }, + { "SC_FOLDDISPLAYTEXT_STANDARD", 1 }, + { "SC_FOLDFLAG_LEVELNUMBERS", 0x0040 }, + { "SC_FOLDFLAG_LINEAFTER_CONTRACTED", 0x0010 }, + { "SC_FOLDFLAG_LINEAFTER_EXPANDED", 0x0008 }, + { "SC_FOLDFLAG_LINEBEFORE_CONTRACTED", 0x0004 }, + { "SC_FOLDFLAG_LINEBEFORE_EXPANDED", 0x0002 }, + { "SC_FOLDFLAG_LINESTATE", 0x0080 }, + { "SC_FOLDLEVELBASE", 0x400 }, + { "SC_FOLDLEVELHEADERFLAG", 0x2000 }, + { "SC_FOLDLEVELNUMBERMASK", 0x0FFF }, + { "SC_FOLDLEVELWHITEFLAG", 0x1000 }, + { "SC_FONT_SIZE_MULTIPLIER", 100 }, + { "SC_IDLESTYLING_AFTERVISIBLE", 2 }, + { "SC_IDLESTYLING_ALL", 3 }, + { "SC_IDLESTYLING_NONE", 0 }, + { "SC_IDLESTYLING_TOVISIBLE", 1 }, + { "SC_IME_INLINE", 1 }, + { "SC_IME_WINDOWED", 0 }, + { "SC_INDICFLAG_VALUEFORE", 1 }, + { "SC_INDICVALUEBIT", 0x1000000 }, + { "SC_INDICVALUEMASK", 0xFFFFFF }, + { "SC_IV_LOOKBOTH", 3 }, + { "SC_IV_LOOKFORWARD", 2 }, + { "SC_IV_NONE", 0 }, + { "SC_IV_REAL", 1 }, + { "SC_LASTSTEPINUNDOREDO", 0x100 }, + { "SC_LINECHARACTERINDEX_NONE", 0 }, + { "SC_LINECHARACTERINDEX_UTF16", 2 }, + { "SC_LINECHARACTERINDEX_UTF32", 1 }, + { "SC_LINE_END_TYPE_DEFAULT", 0 }, + { "SC_LINE_END_TYPE_UNICODE", 1 }, + { "SC_MARGINOPTION_NONE", 0 }, + { "SC_MARGINOPTION_SUBLINESELECT", 1 }, + { "SC_MARGIN_BACK", 2 }, + { "SC_MARGIN_COLOUR", 6 }, + { "SC_MARGIN_FORE", 3 }, + { "SC_MARGIN_NUMBER", 1 }, + { "SC_MARGIN_RTEXT", 5 }, + { "SC_MARGIN_SYMBOL", 0 }, + { "SC_MARGIN_TEXT", 4 }, + { "SC_MARKNUM_FOLDER", 30 }, + { "SC_MARKNUM_FOLDEREND", 25 }, + { "SC_MARKNUM_FOLDERMIDTAIL", 27 }, + { "SC_MARKNUM_FOLDEROPEN", 31 }, + { "SC_MARKNUM_FOLDEROPENMID", 26 }, + { "SC_MARKNUM_FOLDERSUB", 29 }, + { "SC_MARKNUM_FOLDERTAIL", 28 }, + { "SC_MARK_ARROW", 2 }, + { "SC_MARK_ARROWDOWN", 6 }, + { "SC_MARK_ARROWS", 24 }, + { "SC_MARK_AVAILABLE", 28 }, + { "SC_MARK_BACKGROUND", 22 }, + { "SC_MARK_BOOKMARK", 31 }, + { "SC_MARK_BOXMINUS", 14 }, + { "SC_MARK_BOXMINUSCONNECTED", 15 }, + { "SC_MARK_BOXPLUS", 12 }, + { "SC_MARK_BOXPLUSCONNECTED", 13 }, + { "SC_MARK_CHARACTER", 10000 }, + { "SC_MARK_CIRCLE", 0 }, + { "SC_MARK_CIRCLEMINUS", 20 }, + { "SC_MARK_CIRCLEMINUSCONNECTED", 21 }, + { "SC_MARK_CIRCLEPLUS", 18 }, + { "SC_MARK_CIRCLEPLUSCONNECTED", 19 }, + { "SC_MARK_DOTDOTDOT", 23 }, + { "SC_MARK_EMPTY", 5 }, + { "SC_MARK_FULLRECT", 26 }, + { "SC_MARK_LCORNER", 10 }, + { "SC_MARK_LCORNERCURVE", 16 }, + { "SC_MARK_LEFTRECT", 27 }, + { "SC_MARK_MINUS", 7 }, + { "SC_MARK_PIXMAP", 25 }, + { "SC_MARK_PLUS", 8 }, + { "SC_MARK_RGBAIMAGE", 30 }, + { "SC_MARK_ROUNDRECT", 1 }, + { "SC_MARK_SHORTARROW", 4 }, + { "SC_MARK_SMALLRECT", 3 }, + { "SC_MARK_TCORNER", 11 }, + { "SC_MARK_TCORNERCURVE", 17 }, + { "SC_MARK_UNDERLINE", 29 }, + { "SC_MARK_VLINE", 9 }, + { "SC_MASK_FOLDERS", static_cast(0xFE000000) }, + { "SC_MAX_MARGIN", 4 }, + { "SC_MODEVENTMASKALL", 0x3FFFFF }, + { "SC_MOD_BEFOREDELETE", 0x800 }, + { "SC_MOD_BEFOREINSERT", 0x400 }, + { "SC_MOD_CHANGEANNOTATION", 0x20000 }, + { "SC_MOD_CHANGEFOLD", 0x8 }, + { "SC_MOD_CHANGEINDICATOR", 0x4000 }, + { "SC_MOD_CHANGELINESTATE", 0x8000 }, + { "SC_MOD_CHANGEMARGIN", 0x10000 }, + { "SC_MOD_CHANGEMARKER", 0x200 }, + { "SC_MOD_CHANGESTYLE", 0x4 }, + { "SC_MOD_CHANGETABSTOPS", 0x200000 }, + { "SC_MOD_CONTAINER", 0x40000 }, + { "SC_MOD_DELETETEXT", 0x2 }, + { "SC_MOD_INSERTCHECK", 0x100000 }, + { "SC_MOD_INSERTTEXT", 0x1 }, + { "SC_MOD_LEXERSTATE", 0x80000 }, + { "SC_MULTIAUTOC_EACH", 1 }, + { "SC_MULTIAUTOC_ONCE", 0 }, + { "SC_MULTILINEUNDOREDO", 0x1000 }, + { "SC_MULTIPASTE_EACH", 1 }, + { "SC_MULTIPASTE_ONCE", 0 }, + { "SC_MULTISTEPUNDOREDO", 0x80 }, + { "SC_ORDER_CUSTOM", 2 }, + { "SC_ORDER_PERFORMSORT", 1 }, + { "SC_ORDER_PRESORTED", 0 }, + { "SC_PERFORMED_REDO", 0x40 }, + { "SC_PERFORMED_UNDO", 0x20 }, + { "SC_PERFORMED_USER", 0x10 }, + { "SC_PHASES_MULTIPLE", 2 }, + { "SC_PHASES_ONE", 0 }, + { "SC_PHASES_TWO", 1 }, + { "SC_POPUP_ALL", 1 }, + { "SC_POPUP_NEVER", 0 }, + { "SC_POPUP_TEXT", 2 }, + { "SC_PRINT_BLACKONWHITE", 2 }, + { "SC_PRINT_COLOURONWHITE", 3 }, + { "SC_PRINT_COLOURONWHITEDEFAULTBG", 4 }, + { "SC_PRINT_INVERTLIGHT", 1 }, + { "SC_PRINT_NORMAL", 0 }, + { "SC_PRINT_SCREENCOLOURS", 5 }, + { "SC_SEL_LINES", 2 }, + { "SC_SEL_RECTANGLE", 1 }, + { "SC_SEL_STREAM", 0 }, + { "SC_SEL_THIN", 3 }, + { "SC_STARTACTION", 0x2000 }, + { "SC_STATUS_BADALLOC", 2 }, + { "SC_STATUS_FAILURE", 1 }, + { "SC_STATUS_OK", 0 }, + { "SC_STATUS_WARN_REGEX", 1001 }, + { "SC_STATUS_WARN_START", 1000 }, + { "SC_TECHNOLOGY_DEFAULT", 0 }, + { "SC_TECHNOLOGY_DIRECTWRITE", 1 }, + { "SC_TECHNOLOGY_DIRECTWRITEDC", 3 }, + { "SC_TECHNOLOGY_DIRECTWRITERETAIN", 2 }, + { "SC_TIME_FOREVER", 10000000 }, + { "SC_TYPE_BOOLEAN", 0 }, + { "SC_TYPE_INTEGER", 1 }, + { "SC_TYPE_STRING", 2 }, + { "SC_UPDATE_CONTENT", 0x1 }, + { "SC_UPDATE_H_SCROLL", 0x8 }, + { "SC_UPDATE_SELECTION", 0x2 }, + { "SC_UPDATE_V_SCROLL", 0x4 }, + { "SC_WEIGHT_BOLD", 700 }, + { "SC_WEIGHT_NORMAL", 400 }, + { "SC_WEIGHT_SEMIBOLD", 600 }, + { "SC_WRAPINDENT_DEEPINDENT", 3 }, + { "SC_WRAPINDENT_FIXED", 0 }, + { "SC_WRAPINDENT_INDENT", 2 }, + { "SC_WRAPINDENT_SAME", 1 }, + { "SC_WRAPVISUALFLAGLOC_DEFAULT", 0x0000 }, + { "SC_WRAPVISUALFLAGLOC_END_BY_TEXT", 0x0001 }, + { "SC_WRAPVISUALFLAGLOC_START_BY_TEXT", 0x0002 }, + { "SC_WRAPVISUALFLAG_END", 0x0001 }, + { "SC_WRAPVISUALFLAG_MARGIN", 0x0004 }, + { "SC_WRAPVISUALFLAG_NONE", 0x0000 }, + { "SC_WRAPVISUALFLAG_START", 0x0002 }, + { "SC_WRAP_CHAR", 2 }, + { "SC_WRAP_NONE", 0 }, + { "SC_WRAP_WHITESPACE", 3 }, + { "SC_WRAP_WORD", 1 }, + { "STYLE_BRACEBAD", 35 }, + { "STYLE_BRACELIGHT", 34 }, + { "STYLE_CALLTIP", 38 }, + { "STYLE_CONTROLCHAR", 36 }, + { "STYLE_DEFAULT", 32 }, + { "STYLE_FOLDDISPLAYTEXT", 39 }, + { "STYLE_INDENTGUIDE", 37 }, + { "STYLE_LASTPREDEFINED", 39 }, + { "STYLE_LINENUMBER", 33 }, + { "STYLE_MAX", 255 }, + { "UNDO_MAY_COALESCE", 1 }, + { "VISIBLE_SLOP", 0x01 }, + { "VISIBLE_STRICT", 0x04 } +}; + +static std::vector ifaceFunctions = { + { "AddRefDocument", 2376, iface_void, { iface_void, iface_int } }, + { "AddSelection", 2573, iface_void, { iface_position, iface_position } }, + { "AddStyledText", 2002, iface_void, { iface_length, iface_cells } }, + { "AddTabStop", 2676, iface_void, { iface_int, iface_int } }, + { "AddText", 2001, iface_void, { iface_length, iface_string } }, + { "AddUndoAction", 2560, iface_void, { iface_int, iface_int } }, + { "Allocate", 2446, iface_void, { iface_int, iface_void } }, + { "AllocateExtendedStyles", 2553, iface_int, { iface_int, iface_void } }, + { "AllocateLineCharacterIndex", 2711, iface_void, { iface_int, iface_void } }, + { "AllocateSubStyles", 4020, iface_int, { iface_int, iface_int } }, + { "AnnotationClearAll", 2547, iface_void, { iface_void, iface_void } }, + { "AppendText", 2282, iface_void, { iface_length, iface_string } }, + { "AssignCmdKey", 2070, iface_void, { iface_keymod, iface_int } }, + { "AutoCActive", 2102, iface_bool, { iface_void, iface_void } }, + { "AutoCCancel", 2101, iface_void, { iface_void, iface_void } }, + { "AutoCComplete", 2104, iface_void, { iface_void, iface_void } }, + { "AutoCPosStart", 2103, iface_position, { iface_void, iface_void } }, + { "AutoCSelect", 2108, iface_void, { iface_void, iface_string } }, + { "AutoCShow", 2100, iface_void, { iface_int, iface_string } }, + { "AutoCStops", 2105, iface_void, { iface_void, iface_string } }, + { "BackTab", 2328, iface_void, { iface_void, iface_void } }, + { "BeginUndoAction", 2078, iface_void, { iface_void, iface_void } }, + { "BraceBadLight", 2352, iface_void, { iface_position, iface_void } }, + { "BraceBadLightIndicator", 2499, iface_void, { iface_bool, iface_int } }, + { "BraceHighlight", 2351, iface_void, { iface_position, iface_position } }, + { "BraceHighlightIndicator", 2498, iface_void, { iface_bool, iface_int } }, + { "BraceMatch", 2353, iface_position, { iface_position, iface_int } }, + { "CallTipActive", 2202, iface_bool, { iface_void, iface_void } }, + { "CallTipCancel", 2201, iface_void, { iface_void, iface_void } }, + { "CallTipPosStart", 2203, iface_position, { iface_void, iface_void } }, + { "CallTipSetHlt", 2204, iface_void, { iface_int, iface_int } }, + { "CallTipShow", 2200, iface_void, { iface_position, iface_string } }, + { "CanPaste", 2173, iface_bool, { iface_void, iface_void } }, + { "CanRedo", 2016, iface_bool, { iface_void, iface_void } }, + { "CanUndo", 2174, iface_bool, { iface_void, iface_void } }, + { "Cancel", 2325, iface_void, { iface_void, iface_void } }, + { "ChangeInsertion", 2672, iface_void, { iface_length, iface_string } }, + { "ChangeLexerState", 2617, iface_int, { iface_position, iface_position } }, + { "CharLeft", 2304, iface_void, { iface_void, iface_void } }, + { "CharLeftExtend", 2305, iface_void, { iface_void, iface_void } }, + { "CharLeftRectExtend", 2428, iface_void, { iface_void, iface_void } }, + { "CharPositionFromPoint", 2561, iface_position, { iface_int, iface_int } }, + { "CharPositionFromPointClose", 2562, iface_position, { iface_int, iface_int } }, + { "CharRight", 2306, iface_void, { iface_void, iface_void } }, + { "CharRightExtend", 2307, iface_void, { iface_void, iface_void } }, + { "CharRightRectExtend", 2429, iface_void, { iface_void, iface_void } }, + { "ChooseCaretX", 2399, iface_void, { iface_void, iface_void } }, + { "Clear", 2180, iface_void, { iface_void, iface_void } }, + { "ClearAll", 2004, iface_void, { iface_void, iface_void } }, + { "ClearAllCmdKeys", 2072, iface_void, { iface_void, iface_void } }, + { "ClearCmdKey", 2071, iface_void, { iface_keymod, iface_void } }, + { "ClearDocumentStyle", 2005, iface_void, { iface_void, iface_void } }, + { "ClearRegisteredImages", 2408, iface_void, { iface_void, iface_void } }, + { "ClearRepresentation", 2667, iface_void, { iface_string, iface_void } }, + { "ClearSelections", 2571, iface_void, { iface_void, iface_void } }, + { "ClearTabStops", 2675, iface_void, { iface_int, iface_void } }, + { "Colourise", 4003, iface_void, { iface_position, iface_position } }, + { "ContractedFoldNext", 2618, iface_int, { iface_int, iface_void } }, + { "ConvertEOLs", 2029, iface_void, { iface_int, iface_void } }, + { "Copy", 2178, iface_void, { iface_void, iface_void } }, + { "CopyAllowLine", 2519, iface_void, { iface_void, iface_void } }, + { "CopyRange", 2419, iface_void, { iface_position, iface_position } }, + { "CopyText", 2420, iface_void, { iface_length, iface_string } }, + { "CountCharacters", 2633, iface_int, { iface_position, iface_position } }, + { "CountCodeUnits", 2715, iface_int, { iface_position, iface_position } }, + { "CreateDocument", 2375, iface_int, { iface_int, iface_int } }, + { "CreateLoader", 2632, iface_int, { iface_int, iface_int } }, + { "Cut", 2177, iface_void, { iface_void, iface_void } }, + { "DelLineLeft", 2395, iface_void, { iface_void, iface_void } }, + { "DelLineRight", 2396, iface_void, { iface_void, iface_void } }, + { "DelWordLeft", 2335, iface_void, { iface_void, iface_void } }, + { "DelWordRight", 2336, iface_void, { iface_void, iface_void } }, + { "DelWordRightEnd", 2518, iface_void, { iface_void, iface_void } }, + { "DeleteBack", 2326, iface_void, { iface_void, iface_void } }, + { "DeleteBackNotLine", 2344, iface_void, { iface_void, iface_void } }, + { "DeleteRange", 2645, iface_void, { iface_position, iface_int } }, + { "DescribeKeyWordSets", 4017, iface_int, { iface_void, iface_stringresult } }, + { "DescribeProperty", 4016, iface_int, { iface_string, iface_stringresult } }, + { "DescriptionOfStyle", 4032, iface_int, { iface_int, iface_stringresult } }, + { "DocLineFromVisible", 2221, iface_int, { iface_int, iface_void } }, + { "DocumentEnd", 2318, iface_void, { iface_void, iface_void } }, + { "DocumentEndExtend", 2319, iface_void, { iface_void, iface_void } }, + { "DocumentStart", 2316, iface_void, { iface_void, iface_void } }, + { "DocumentStartExtend", 2317, iface_void, { iface_void, iface_void } }, + { "DropSelectionN", 2671, iface_void, { iface_int, iface_void } }, + { "EditToggleOvertype", 2324, iface_void, { iface_void, iface_void } }, + { "EmptyUndoBuffer", 2175, iface_void, { iface_void, iface_void } }, + { "EncodedFromUTF8", 2449, iface_int, { iface_string, iface_stringresult } }, + { "EndUndoAction", 2079, iface_void, { iface_void, iface_void } }, + { "EnsureVisible", 2232, iface_void, { iface_int, iface_void } }, + { "EnsureVisibleEnforcePolicy", 2234, iface_void, { iface_int, iface_void } }, + { "ExpandChildren", 2239, iface_void, { iface_int, iface_int } }, + { "FindColumn", 2456, iface_int, { iface_int, iface_int } }, + { "FindIndicatorFlash", 2641, iface_void, { iface_position, iface_position } }, + { "FindIndicatorHide", 2642, iface_void, { iface_void, iface_void } }, + { "FindIndicatorShow", 2640, iface_void, { iface_position, iface_position } }, + { "FindText", 2150, iface_position, { iface_int, iface_findtext } }, + { "FoldAll", 2662, iface_void, { iface_int, iface_void } }, + { "FoldChildren", 2238, iface_void, { iface_int, iface_int } }, + { "FoldLine", 2237, iface_void, { iface_int, iface_int } }, + { "FormFeed", 2330, iface_void, { iface_void, iface_void } }, + { "FormatRange", 2151, iface_position, { iface_bool, iface_formatrange } }, + { "FreeSubStyles", 4023, iface_void, { iface_void, iface_void } }, + { "GetCurLine", 2027, iface_int, { iface_length, iface_stringresult } }, + { "GetHotspotActiveBack", 2495, iface_colour, { iface_void, iface_void } }, + { "GetHotspotActiveFore", 2494, iface_colour, { iface_void, iface_void } }, + { "GetLastChild", 2224, iface_int, { iface_int, iface_int } }, + { "GetLine", 2153, iface_int, { iface_int, iface_stringresult } }, + { "GetLineSelEndPosition", 2425, iface_position, { iface_int, iface_void } }, + { "GetLineSelStartPosition", 2424, iface_position, { iface_int, iface_void } }, + { "GetNextTabStop", 2677, iface_int, { iface_int, iface_int } }, + { "GetPropertyInt", 4010, iface_int, { iface_string, iface_int } }, + { "GetRangePointer", 2643, iface_int, { iface_position, iface_int } }, + { "GetSelText", 2161, iface_int, { iface_void, iface_stringresult } }, + { "GetStyledText", 2015, iface_int, { iface_void, iface_textrange } }, + { "GetText", 2182, iface_int, { iface_length, iface_stringresult } }, + { "GetTextRange", 2162, iface_int, { iface_void, iface_textrange } }, + { "GotoLine", 2024, iface_void, { iface_int, iface_void } }, + { "GotoPos", 2025, iface_void, { iface_position, iface_void } }, + { "GrabFocus", 2400, iface_void, { iface_void, iface_void } }, + { "HideLines", 2227, iface_void, { iface_int, iface_int } }, + { "HideSelection", 2163, iface_void, { iface_bool, iface_void } }, + { "Home", 2312, iface_void, { iface_void, iface_void } }, + { "HomeDisplay", 2345, iface_void, { iface_void, iface_void } }, + { "HomeDisplayExtend", 2346, iface_void, { iface_void, iface_void } }, + { "HomeExtend", 2313, iface_void, { iface_void, iface_void } }, + { "HomeRectExtend", 2430, iface_void, { iface_void, iface_void } }, + { "HomeWrap", 2349, iface_void, { iface_void, iface_void } }, + { "HomeWrapExtend", 2450, iface_void, { iface_void, iface_void } }, + { "IndexPositionFromLine", 2714, iface_position, { iface_int, iface_int } }, + { "IndicatorAllOnFor", 2506, iface_int, { iface_position, iface_void } }, + { "IndicatorClearRange", 2505, iface_void, { iface_position, iface_int } }, + { "IndicatorEnd", 2509, iface_int, { iface_int, iface_position } }, + { "IndicatorFillRange", 2504, iface_void, { iface_position, iface_int } }, + { "IndicatorStart", 2508, iface_int, { iface_int, iface_position } }, + { "IndicatorValueAt", 2507, iface_int, { iface_int, iface_position } }, + { "InsertText", 2003, iface_void, { iface_position, iface_string } }, + { "IsRangeWord", 2691, iface_bool, { iface_position, iface_position } }, + { "LineCopy", 2455, iface_void, { iface_void, iface_void } }, + { "LineCut", 2337, iface_void, { iface_void, iface_void } }, + { "LineDelete", 2338, iface_void, { iface_void, iface_void } }, + { "LineDown", 2300, iface_void, { iface_void, iface_void } }, + { "LineDownExtend", 2301, iface_void, { iface_void, iface_void } }, + { "LineDownRectExtend", 2426, iface_void, { iface_void, iface_void } }, + { "LineDuplicate", 2404, iface_void, { iface_void, iface_void } }, + { "LineEnd", 2314, iface_void, { iface_void, iface_void } }, + { "LineEndDisplay", 2347, iface_void, { iface_void, iface_void } }, + { "LineEndDisplayExtend", 2348, iface_void, { iface_void, iface_void } }, + { "LineEndExtend", 2315, iface_void, { iface_void, iface_void } }, + { "LineEndRectExtend", 2432, iface_void, { iface_void, iface_void } }, + { "LineEndWrap", 2451, iface_void, { iface_void, iface_void } }, + { "LineEndWrapExtend", 2452, iface_void, { iface_void, iface_void } }, + { "LineFromIndexPosition", 2713, iface_int, { iface_position, iface_int } }, + { "LineFromPosition", 2166, iface_int, { iface_position, iface_void } }, + { "LineLength", 2350, iface_int, { iface_int, iface_void } }, + { "LineReverse", 2354, iface_void, { iface_void, iface_void } }, + { "LineScroll", 2168, iface_void, { iface_int, iface_int } }, + { "LineScrollDown", 2342, iface_void, { iface_void, iface_void } }, + { "LineScrollUp", 2343, iface_void, { iface_void, iface_void } }, + { "LineTranspose", 2339, iface_void, { iface_void, iface_void } }, + { "LineUp", 2302, iface_void, { iface_void, iface_void } }, + { "LineUpExtend", 2303, iface_void, { iface_void, iface_void } }, + { "LineUpRectExtend", 2427, iface_void, { iface_void, iface_void } }, + { "LinesJoin", 2288, iface_void, { iface_void, iface_void } }, + { "LinesSplit", 2289, iface_void, { iface_int, iface_void } }, + { "LoadLexerLibrary", 4007, iface_void, { iface_void, iface_string } }, + { "LowerCase", 2340, iface_void, { iface_void, iface_void } }, + { "MarginTextClearAll", 2536, iface_void, { iface_void, iface_void } }, + { "MarkerAdd", 2043, iface_int, { iface_int, iface_int } }, + { "MarkerAddSet", 2466, iface_void, { iface_int, iface_int } }, + { "MarkerDefine", 2040, iface_void, { iface_int, iface_int } }, + { "MarkerDefinePixmap", 2049, iface_void, { iface_int, iface_string } }, + { "MarkerDefineRGBAImage", 2626, iface_void, { iface_int, iface_string } }, + { "MarkerDelete", 2044, iface_void, { iface_int, iface_int } }, + { "MarkerDeleteAll", 2045, iface_void, { iface_int, iface_void } }, + { "MarkerDeleteHandle", 2018, iface_void, { iface_int, iface_void } }, + { "MarkerEnableHighlight", 2293, iface_void, { iface_bool, iface_void } }, + { "MarkerGet", 2046, iface_int, { iface_int, iface_void } }, + { "MarkerLineFromHandle", 2017, iface_int, { iface_int, iface_void } }, + { "MarkerNext", 2047, iface_int, { iface_int, iface_int } }, + { "MarkerPrevious", 2048, iface_int, { iface_int, iface_int } }, + { "MarkerSymbolDefined", 2529, iface_int, { iface_int, iface_void } }, + { "MoveCaretInsideView", 2401, iface_void, { iface_void, iface_void } }, + { "MoveSelectedLinesDown", 2621, iface_void, { iface_void, iface_void } }, + { "MoveSelectedLinesUp", 2620, iface_void, { iface_void, iface_void } }, + { "MultiEdgeAddLine", 2694, iface_void, { iface_int, iface_colour } }, + { "MultiEdgeClearAll", 2695, iface_void, { iface_void, iface_void } }, + { "MultipleSelectAddEach", 2689, iface_void, { iface_void, iface_void } }, + { "MultipleSelectAddNext", 2688, iface_void, { iface_void, iface_void } }, + { "NameOfStyle", 4030, iface_int, { iface_int, iface_stringresult } }, + { "NewLine", 2329, iface_void, { iface_void, iface_void } }, + { "Null", 2172, iface_void, { iface_void, iface_void } }, + { "PageDown", 2322, iface_void, { iface_void, iface_void } }, + { "PageDownExtend", 2323, iface_void, { iface_void, iface_void } }, + { "PageDownRectExtend", 2434, iface_void, { iface_void, iface_void } }, + { "PageUp", 2320, iface_void, { iface_void, iface_void } }, + { "PageUpExtend", 2321, iface_void, { iface_void, iface_void } }, + { "PageUpRectExtend", 2433, iface_void, { iface_void, iface_void } }, + { "ParaDown", 2413, iface_void, { iface_void, iface_void } }, + { "ParaDownExtend", 2414, iface_void, { iface_void, iface_void } }, + { "ParaUp", 2415, iface_void, { iface_void, iface_void } }, + { "ParaUpExtend", 2416, iface_void, { iface_void, iface_void } }, + { "Paste", 2179, iface_void, { iface_void, iface_void } }, + { "PointXFromPosition", 2164, iface_int, { iface_void, iface_position } }, + { "PointYFromPosition", 2165, iface_int, { iface_void, iface_position } }, + { "PositionAfter", 2418, iface_position, { iface_position, iface_void } }, + { "PositionBefore", 2417, iface_position, { iface_position, iface_void } }, + { "PositionFromLine", 2167, iface_position, { iface_int, iface_void } }, + { "PositionFromPoint", 2022, iface_position, { iface_int, iface_int } }, + { "PositionFromPointClose", 2023, iface_position, { iface_int, iface_int } }, + { "PositionRelative", 2670, iface_position, { iface_position, iface_int } }, + { "PositionRelativeCodeUnits", 2716, iface_position, { iface_position, iface_int } }, + { "PrivateLexerCall", 4013, iface_int, { iface_int, iface_int } }, + { "PropertyNames", 4014, iface_int, { iface_void, iface_stringresult } }, + { "PropertyType", 4015, iface_int, { iface_string, iface_void } }, + { "Redo", 2011, iface_void, { iface_void, iface_void } }, + { "RegisterImage", 2405, iface_void, { iface_int, iface_string } }, + { "RegisterRGBAImage", 2627, iface_void, { iface_int, iface_string } }, + { "ReleaseAllExtendedStyles", 2552, iface_void, { iface_void, iface_void } }, + { "ReleaseDocument", 2377, iface_void, { iface_void, iface_int } }, + { "ReleaseLineCharacterIndex", 2712, iface_void, { iface_int, iface_void } }, + { "ReplaceSel", 2170, iface_void, { iface_void, iface_string } }, + { "ReplaceTarget", 2194, iface_int, { iface_length, iface_string } }, + { "ReplaceTargetRE", 2195, iface_int, { iface_length, iface_string } }, + { "RotateSelection", 2606, iface_void, { iface_void, iface_void } }, + { "ScrollCaret", 2169, iface_void, { iface_void, iface_void } }, + { "ScrollRange", 2569, iface_void, { iface_position, iface_position } }, + { "ScrollToEnd", 2629, iface_void, { iface_void, iface_void } }, + { "ScrollToStart", 2628, iface_void, { iface_void, iface_void } }, + { "SearchAnchor", 2366, iface_void, { iface_void, iface_void } }, + { "SearchInTarget", 2197, iface_int, { iface_length, iface_string } }, + { "SearchNext", 2367, iface_int, { iface_int, iface_string } }, + { "SearchPrev", 2368, iface_int, { iface_int, iface_string } }, + { "SelectAll", 2013, iface_void, { iface_void, iface_void } }, + { "SelectionDuplicate", 2469, iface_void, { iface_void, iface_void } }, + { "SetCharsDefault", 2444, iface_void, { iface_void, iface_void } }, + { "SetEmptySelection", 2556, iface_void, { iface_position, iface_void } }, + { "SetFoldMarginColour", 2290, iface_void, { iface_bool, iface_colour } }, + { "SetFoldMarginHiColour", 2291, iface_void, { iface_bool, iface_colour } }, + { "SetHotspotActiveBack", 2411, iface_void, { iface_bool, iface_colour } }, + { "SetHotspotActiveFore", 2410, iface_void, { iface_bool, iface_colour } }, + { "SetLengthForEncode", 2448, iface_void, { iface_int, iface_void } }, + { "SetSavePoint", 2014, iface_void, { iface_void, iface_void } }, + { "SetSel", 2160, iface_void, { iface_position, iface_position } }, + { "SetSelBack", 2068, iface_void, { iface_bool, iface_colour } }, + { "SetSelFore", 2067, iface_void, { iface_bool, iface_colour } }, + { "SetSelection", 2572, iface_void, { iface_position, iface_position } }, + { "SetStyling", 2033, iface_void, { iface_length, iface_int } }, + { "SetStylingEx", 2073, iface_void, { iface_length, iface_string } }, + { "SetTargetRange", 2686, iface_void, { iface_position, iface_position } }, + { "SetText", 2181, iface_void, { iface_void, iface_string } }, + { "SetVisiblePolicy", 2394, iface_void, { iface_int, iface_int } }, + { "SetWhitespaceBack", 2085, iface_void, { iface_bool, iface_colour } }, + { "SetWhitespaceFore", 2084, iface_void, { iface_bool, iface_colour } }, + { "SetXCaretPolicy", 2402, iface_void, { iface_int, iface_int } }, + { "SetYCaretPolicy", 2403, iface_void, { iface_int, iface_int } }, + { "ShowLines", 2226, iface_void, { iface_int, iface_int } }, + { "StartRecord", 3001, iface_void, { iface_void, iface_void } }, + { "StartStyling", 2032, iface_void, { iface_position, iface_int } }, + { "StopRecord", 3002, iface_void, { iface_void, iface_void } }, + { "StutteredPageDown", 2437, iface_void, { iface_void, iface_void } }, + { "StutteredPageDownExtend", 2438, iface_void, { iface_void, iface_void } }, + { "StutteredPageUp", 2435, iface_void, { iface_void, iface_void } }, + { "StutteredPageUpExtend", 2436, iface_void, { iface_void, iface_void } }, + { "StyleClearAll", 2050, iface_void, { iface_void, iface_void } }, + { "StyleResetDefault", 2058, iface_void, { iface_void, iface_void } }, + { "SwapMainAnchorCaret", 2607, iface_void, { iface_void, iface_void } }, + { "Tab", 2327, iface_void, { iface_void, iface_void } }, + { "TagsOfStyle", 4031, iface_int, { iface_int, iface_stringresult } }, + { "TargetAsUTF8", 2447, iface_int, { iface_void, iface_stringresult } }, + { "TargetFromSelection", 2287, iface_void, { iface_void, iface_void } }, + { "TargetWholeDocument", 2690, iface_void, { iface_void, iface_void } }, + { "TextHeight", 2279, iface_int, { iface_int, iface_void } }, + { "TextWidth", 2276, iface_int, { iface_int, iface_string } }, + { "ToggleCaretSticky", 2459, iface_void, { iface_void, iface_void } }, + { "ToggleFold", 2231, iface_void, { iface_int, iface_void } }, + { "ToggleFoldShowText", 2700, iface_void, { iface_int, iface_string } }, + { "Undo", 2176, iface_void, { iface_void, iface_void } }, + { "UpperCase", 2341, iface_void, { iface_void, iface_void } }, + { "UsePopUp", 2371, iface_void, { iface_int, iface_void } }, + { "UserListShow", 2117, iface_void, { iface_int, iface_string } }, + { "VCHome", 2331, iface_void, { iface_void, iface_void } }, + { "VCHomeDisplay", 2652, iface_void, { iface_void, iface_void } }, + { "VCHomeDisplayExtend", 2653, iface_void, { iface_void, iface_void } }, + { "VCHomeExtend", 2332, iface_void, { iface_void, iface_void } }, + { "VCHomeRectExtend", 2431, iface_void, { iface_void, iface_void } }, + { "VCHomeWrap", 2453, iface_void, { iface_void, iface_void } }, + { "VCHomeWrapExtend", 2454, iface_void, { iface_void, iface_void } }, + { "VerticalCentreCaret", 2619, iface_void, { iface_void, iface_void } }, + { "VisibleFromDocLine", 2220, iface_int, { iface_int, iface_void } }, + { "WordEndPosition", 2267, iface_int, { iface_position, iface_bool } }, + { "WordLeft", 2308, iface_void, { iface_void, iface_void } }, + { "WordLeftEnd", 2439, iface_void, { iface_void, iface_void } }, + { "WordLeftEndExtend", 2440, iface_void, { iface_void, iface_void } }, + { "WordLeftExtend", 2309, iface_void, { iface_void, iface_void } }, + { "WordPartLeft", 2390, iface_void, { iface_void, iface_void } }, + { "WordPartLeftExtend", 2391, iface_void, { iface_void, iface_void } }, + { "WordPartRight", 2392, iface_void, { iface_void, iface_void } }, + { "WordPartRightExtend", 2393, iface_void, { iface_void, iface_void } }, + { "WordRight", 2310, iface_void, { iface_void, iface_void } }, + { "WordRightEnd", 2441, iface_void, { iface_void, iface_void } }, + { "WordRightEndExtend", 2442, iface_void, { iface_void, iface_void } }, + { "WordRightExtend", 2311, iface_void, { iface_void, iface_void } }, + { "WordStartPosition", 2266, iface_int, { iface_position, iface_bool } }, + { "WrapCount", 2235, iface_int, { iface_int, iface_void } }, + { "ZoomIn", 2333, iface_void, { iface_void, iface_void } }, + { "ZoomOut", 2334, iface_void, { iface_void, iface_void } } +}; + +static std::vector ifaceProperties = { + { "Accessibility", 2703, 2702, iface_int, iface_void }, + { "AdditionalCaretFore", 2605, 2604, iface_colour, iface_void }, + { "AdditionalCaretsBlink", 2568, 2567, iface_bool, iface_void }, + { "AdditionalCaretsVisible", 2609, 2608, iface_bool, iface_void }, + { "AdditionalSelAlpha", 2603, 2602, iface_int, iface_void }, + { "AdditionalSelBack", 0, 2601, iface_colour, iface_void }, + { "AdditionalSelFore", 0, 2600, iface_colour, iface_void }, + { "AdditionalSelectionTyping", 2566, 2565, iface_bool, iface_void }, + { "AllLinesVisible", 2236, 0, iface_bool, iface_void }, + { "Anchor", 2009, 2026, iface_position, iface_void }, + { "AnnotationLines", 2546, 0, iface_int, iface_int }, + { "AnnotationStyle", 2543, 2542, iface_int, iface_int }, + { "AnnotationStyleOffset", 2551, 2550, iface_int, iface_void }, + { "AnnotationStyles", 2545, 2544, iface_stringresult, iface_int }, + { "AnnotationText", 2541, 2540, iface_stringresult, iface_int }, + { "AnnotationVisible", 2549, 2548, iface_int, iface_void }, + { "AutoCAutoHide", 2119, 2118, iface_bool, iface_void }, + { "AutoCCancelAtStart", 2111, 2110, iface_bool, iface_void }, + { "AutoCCaseInsensitiveBehaviour", 2635, 2634, iface_int, iface_void }, + { "AutoCChooseSingle", 2114, 2113, iface_bool, iface_void }, + { "AutoCCurrent", 2445, 0, iface_int, iface_void }, + { "AutoCCurrentText", 2610, 0, iface_stringresult, iface_void }, + { "AutoCDropRestOfWord", 2271, 2270, iface_bool, iface_void }, + { "AutoCFillUps", 0, 2112, iface_string, iface_void }, + { "AutoCIgnoreCase", 2116, 2115, iface_bool, iface_void }, + { "AutoCMaxHeight", 2211, 2210, iface_int, iface_void }, + { "AutoCMaxWidth", 2209, 2208, iface_int, iface_void }, + { "AutoCMulti", 2637, 2636, iface_int, iface_void }, + { "AutoCOrder", 2661, 2660, iface_int, iface_void }, + { "AutoCSeparator", 2107, 2106, iface_int, iface_void }, + { "AutoCTypeSeparator", 2285, 2286, iface_int, iface_void }, + { "AutomaticFold", 2664, 2663, iface_int, iface_void }, + { "BackSpaceUnIndents", 2263, 2262, iface_bool, iface_void }, + { "Bidirectional", 2708, 2709, iface_int, iface_void }, + { "BufferedDraw", 2034, 2035, iface_bool, iface_void }, + { "CallTipBack", 0, 2205, iface_colour, iface_void }, + { "CallTipFore", 0, 2206, iface_colour, iface_void }, + { "CallTipForeHlt", 0, 2207, iface_colour, iface_void }, + { "CallTipPosStart", 0, 2214, iface_int, iface_void }, + { "CallTipPosition", 0, 2213, iface_bool, iface_void }, + { "CallTipUseStyle", 0, 2212, iface_int, iface_void }, + { "CaretFore", 2138, 2069, iface_colour, iface_void }, + { "CaretLineBack", 2097, 2098, iface_colour, iface_void }, + { "CaretLineBackAlpha", 2471, 2470, iface_int, iface_void }, + { "CaretLineFrame", 2704, 2705, iface_int, iface_void }, + { "CaretLineVisible", 2095, 2096, iface_bool, iface_void }, + { "CaretLineVisibleAlways", 2654, 2655, iface_bool, iface_void }, + { "CaretPeriod", 2075, 2076, iface_int, iface_void }, + { "CaretSticky", 2457, 2458, iface_int, iface_void }, + { "CaretStyle", 2513, 2512, iface_int, iface_void }, + { "CaretWidth", 2189, 2188, iface_int, iface_void }, + { "CharAt", 2007, 0, iface_int, iface_position }, + { "CharacterPointer", 2520, 0, iface_int, iface_void }, + { "CodePage", 2137, 2037, iface_int, iface_void }, + { "Column", 2129, 0, iface_int, iface_position }, + { "CommandEvents", 2718, 2717, iface_bool, iface_void }, + { "ControlCharSymbol", 2389, 2388, iface_int, iface_void }, + { "CurrentPos", 2008, 2141, iface_position, iface_void }, + { "Cursor", 2387, 2386, iface_int, iface_void }, + { "DirectFunction", 2184, 0, iface_int, iface_void }, + { "DirectPointer", 2185, 0, iface_int, iface_void }, + { "DistanceToSecondaryStyles", 4025, 0, iface_int, iface_void }, + { "DocPointer", 2357, 2358, iface_int, iface_void }, + { "DocumentOptions", 2379, 0, iface_int, iface_void }, + { "EOLMode", 2030, 2031, iface_int, iface_void }, + { "EdgeColour", 2364, 2365, iface_colour, iface_void }, + { "EdgeColumn", 2360, 2361, iface_int, iface_void }, + { "EdgeMode", 2362, 2363, iface_int, iface_void }, + { "EndAtLastLine", 2278, 2277, iface_bool, iface_void }, + { "EndStyled", 2028, 0, iface_position, iface_void }, + { "ExtraAscent", 2526, 2525, iface_int, iface_void }, + { "ExtraDescent", 2528, 2527, iface_int, iface_void }, + { "FirstVisibleLine", 2152, 2613, iface_int, iface_void }, + { "Focus", 2381, 2380, iface_bool, iface_void }, + { "FoldDisplayTextStyle", 0, 2701, iface_int, iface_void }, + { "FoldExpanded", 2230, 2229, iface_bool, iface_int }, + { "FoldFlags", 0, 2233, iface_int, iface_void }, + { "FoldLevel", 2223, 2222, iface_int, iface_int }, + { "FoldParent", 2225, 0, iface_int, iface_int }, + { "FontQuality", 2612, 2611, iface_int, iface_void }, + { "GapPosition", 2644, 0, iface_position, iface_void }, + { "HScrollBar", 2131, 2130, iface_bool, iface_void }, + { "HighlightGuide", 2135, 2134, iface_int, iface_void }, + { "HotspotActiveUnderline", 2496, 2412, iface_bool, iface_void }, + { "HotspotSingleLine", 2497, 2421, iface_bool, iface_void }, + { "IMEInteraction", 2678, 2679, iface_int, iface_void }, + { "Identifier", 2623, 2622, iface_int, iface_void }, + { "Identifiers", 0, 4024, iface_string, iface_int }, + { "IdleStyling", 2693, 2692, iface_int, iface_void }, + { "Indent", 2123, 2122, iface_int, iface_void }, + { "IndentationGuides", 2133, 2132, iface_int, iface_void }, + { "IndicAlpha", 2524, 2523, iface_int, iface_int }, + { "IndicFlags", 2685, 2684, iface_int, iface_int }, + { "IndicFore", 2083, 2082, iface_colour, iface_int }, + { "IndicHoverFore", 2683, 2682, iface_colour, iface_int }, + { "IndicHoverStyle", 2681, 2680, iface_int, iface_int }, + { "IndicOutlineAlpha", 2559, 2558, iface_int, iface_int }, + { "IndicStyle", 2081, 2080, iface_int, iface_int }, + { "IndicUnder", 2511, 2510, iface_bool, iface_int }, + { "IndicatorCurrent", 2501, 2500, iface_int, iface_void }, + { "IndicatorValue", 2503, 2502, iface_int, iface_void }, + { "KeyWords", 0, 4005, iface_string, iface_int }, + { "LayoutCache", 2273, 2272, iface_int, iface_void }, + { "Length", 2006, 0, iface_int, iface_void }, + { "Lexer", 4002, 4001, iface_int, iface_void }, + { "LexerLanguage", 4012, 4006, iface_stringresult, iface_void }, + { "LineCharacterIndex", 2710, 0, iface_int, iface_void }, + { "LineCount", 2154, 0, iface_int, iface_void }, + { "LineEndPosition", 2136, 0, iface_position, iface_int }, + { "LineEndTypesActive", 2658, 0, iface_int, iface_void }, + { "LineEndTypesAllowed", 2657, 2656, iface_int, iface_void }, + { "LineEndTypesSupported", 4018, 0, iface_int, iface_void }, + { "LineIndentPosition", 2128, 0, iface_position, iface_int }, + { "LineIndentation", 2127, 2126, iface_int, iface_int }, + { "LineState", 2093, 2092, iface_int, iface_int }, + { "LineVisible", 2228, 0, iface_bool, iface_int }, + { "LinesOnScreen", 2370, 0, iface_int, iface_void }, + { "MainSelection", 2575, 2574, iface_int, iface_void }, + { "MarginBackN", 2251, 2250, iface_colour, iface_int }, + { "MarginCursorN", 2249, 2248, iface_int, iface_int }, + { "MarginLeft", 2156, 2155, iface_int, iface_void }, + { "MarginMaskN", 2245, 2244, iface_int, iface_int }, + { "MarginOptions", 2557, 2539, iface_int, iface_void }, + { "MarginRight", 2158, 2157, iface_int, iface_void }, + { "MarginSensitiveN", 2247, 2246, iface_bool, iface_int }, + { "MarginStyle", 2533, 2532, iface_int, iface_int }, + { "MarginStyleOffset", 2538, 2537, iface_int, iface_void }, + { "MarginStyles", 2535, 2534, iface_stringresult, iface_int }, + { "MarginText", 2531, 2530, iface_stringresult, iface_int }, + { "MarginTypeN", 2241, 2240, iface_int, iface_int }, + { "MarginWidthN", 2243, 2242, iface_int, iface_int }, + { "Margins", 2253, 2252, iface_int, iface_void }, + { "MarkerAlpha", 0, 2476, iface_int, iface_int }, + { "MarkerBack", 0, 2042, iface_colour, iface_int }, + { "MarkerBackSelected", 0, 2292, iface_colour, iface_int }, + { "MarkerFore", 0, 2041, iface_colour, iface_int }, + { "MaxLineState", 2094, 0, iface_int, iface_void }, + { "ModEventMask", 2378, 2359, iface_int, iface_void }, + { "Modify", 2159, 0, iface_bool, iface_void }, + { "MouseDownCaptures", 2385, 2384, iface_bool, iface_void }, + { "MouseDwellTime", 2265, 2264, iface_int, iface_void }, + { "MouseSelectionRectangularSwitch", 2669, 2668, iface_bool, iface_void }, + { "MouseWheelCaptures", 2697, 2696, iface_bool, iface_void }, + { "MoveExtendsSelection", 2706, 0, iface_bool, iface_void }, + { "MultiPaste", 2615, 2614, iface_int, iface_void }, + { "MultipleSelection", 2564, 2563, iface_bool, iface_void }, + { "NamedStyles", 4029, 0, iface_int, iface_void }, + { "Overtype", 2187, 2186, iface_bool, iface_void }, + { "PasteConvertEndings", 2468, 2467, iface_bool, iface_void }, + { "PhasesDraw", 2673, 2674, iface_int, iface_void }, + { "PositionCache", 2515, 2514, iface_int, iface_void }, + { "PrimaryStyleFromStyle", 4028, 0, iface_int, iface_int }, + { "PrintColourMode", 2149, 2148, iface_int, iface_void }, + { "PrintMagnification", 2147, 2146, iface_int, iface_void }, + { "PrintWrapMode", 2407, 2406, iface_int, iface_void }, + { "Property", 4008, 4004, iface_stringresult, iface_string }, + { "PropertyExpanded", 4009, 0, iface_stringresult, iface_string }, + { "PunctuationChars", 2649, 2648, iface_stringresult, iface_void }, + { "RGBAImageHeight", 0, 2625, iface_int, iface_void }, + { "RGBAImageScale", 0, 2651, iface_int, iface_void }, + { "RGBAImageWidth", 0, 2624, iface_int, iface_void }, + { "ReadOnly", 2140, 2171, iface_bool, iface_void }, + { "RectangularSelectionAnchor", 2591, 2590, iface_position, iface_void }, + { "RectangularSelectionAnchorVirtualSpace", 2595, 2594, iface_int, iface_void }, + { "RectangularSelectionCaret", 2589, 2588, iface_position, iface_void }, + { "RectangularSelectionCaretVirtualSpace", 2593, 2592, iface_int, iface_void }, + { "RectangularSelectionModifier", 2599, 2598, iface_int, iface_void }, + { "Representation", 2666, 2665, iface_stringresult, iface_string }, + { "ScrollWidth", 2275, 2274, iface_int, iface_void }, + { "ScrollWidthTracking", 2517, 2516, iface_bool, iface_void }, + { "SearchFlags", 2199, 2198, iface_int, iface_void }, + { "SelAlpha", 2477, 2478, iface_int, iface_void }, + { "SelEOLFilled", 2479, 2480, iface_bool, iface_void }, + { "SelectionEmpty", 2650, 0, iface_bool, iface_void }, + { "SelectionEnd", 2145, 2144, iface_position, iface_void }, + { "SelectionIsRectangle", 2372, 0, iface_bool, iface_void }, + { "SelectionMode", 2423, 2422, iface_int, iface_void }, + { "SelectionNAnchor", 2579, 2578, iface_position, iface_int }, + { "SelectionNAnchorVirtualSpace", 2583, 2582, iface_int, iface_int }, + { "SelectionNCaret", 2577, 2576, iface_position, iface_int }, + { "SelectionNCaretVirtualSpace", 2581, 2580, iface_int, iface_int }, + { "SelectionNEnd", 2587, 2586, iface_position, iface_int }, + { "SelectionNStart", 2585, 2584, iface_position, iface_int }, + { "SelectionStart", 2143, 2142, iface_position, iface_void }, + { "Selections", 2570, 0, iface_int, iface_void }, + { "Status", 2383, 2382, iface_int, iface_void }, + { "StyleAt", 2010, 0, iface_int, iface_position }, + { "StyleBack", 2482, 2052, iface_colour, iface_int }, + { "StyleBold", 2483, 2053, iface_bool, iface_int }, + { "StyleCase", 2489, 2060, iface_int, iface_int }, + { "StyleChangeable", 2492, 2099, iface_bool, iface_int }, + { "StyleCharacterSet", 2490, 2066, iface_int, iface_int }, + { "StyleEOLFilled", 2487, 2057, iface_bool, iface_int }, + { "StyleFont", 2486, 2056, iface_stringresult, iface_int }, + { "StyleFore", 2481, 2051, iface_colour, iface_int }, + { "StyleFromSubStyle", 4027, 0, iface_int, iface_int }, + { "StyleHotSpot", 2493, 2409, iface_bool, iface_int }, + { "StyleItalic", 2484, 2054, iface_bool, iface_int }, + { "StyleSize", 2485, 2055, iface_int, iface_int }, + { "StyleSizeFractional", 2062, 2061, iface_int, iface_int }, + { "StyleUnderline", 2488, 2059, iface_bool, iface_int }, + { "StyleVisible", 2491, 2074, iface_bool, iface_int }, + { "StyleWeight", 2064, 2063, iface_int, iface_int }, + { "SubStyleBases", 4026, 0, iface_stringresult, iface_void }, + { "SubStylesLength", 4022, 0, iface_int, iface_int }, + { "SubStylesStart", 4021, 0, iface_int, iface_int }, + { "TabDrawMode", 2698, 2699, iface_int, iface_void }, + { "TabIndents", 2261, 2260, iface_bool, iface_void }, + { "TabWidth", 2121, 2036, iface_int, iface_void }, + { "Tag", 2616, 0, iface_stringresult, iface_int }, + { "TargetEnd", 2193, 2192, iface_position, iface_void }, + { "TargetStart", 2191, 2190, iface_position, iface_void }, + { "TargetText", 2687, 0, iface_stringresult, iface_void }, + { "Technology", 2631, 2630, iface_int, iface_void }, + { "TextLength", 2183, 0, iface_int, iface_void }, + { "UndoCollection", 2019, 2012, iface_bool, iface_void }, + { "UseTabs", 2125, 2124, iface_bool, iface_void }, + { "VScrollBar", 2281, 2280, iface_bool, iface_void }, + { "ViewEOL", 2355, 2356, iface_bool, iface_void }, + { "ViewWS", 2020, 2021, iface_int, iface_void }, + { "VirtualSpaceOptions", 2597, 2596, iface_int, iface_void }, + { "WhitespaceChars", 2647, 2443, iface_stringresult, iface_void }, + { "WhitespaceSize", 2087, 2086, iface_int, iface_void }, + { "WordChars", 2646, 2077, iface_stringresult, iface_void }, + { "WrapIndentMode", 2473, 2472, iface_int, iface_void }, + { "WrapMode", 2269, 2268, iface_int, iface_void }, + { "WrapStartIndent", 2465, 2464, iface_int, iface_void }, + { "WrapVisualFlags", 2461, 2460, iface_int, iface_void }, + { "WrapVisualFlagsLocation", 2463, 2462, iface_int, iface_void }, + { "XOffset", 2398, 2397, iface_int, iface_void }, + { "Zoom", 2374, 2373, iface_int, iface_void } +}; + +enum { + ifaceFunctionCount = 301, + ifaceConstantCount = 2526, + ifacePropertyCount = 228 +}; + +//--Autogenerated + +IFaceTable SciIFaceTable("SCI_", ifaceFunctions, ifaceConstants, ifaceProperties); diff --git a/src/NotepadNext/SciIFaceTable.h b/src/NotepadNext/SciIFaceTable.h new file mode 100644 index 000000000..cd5dd08ca --- /dev/null +++ b/src/NotepadNext/SciIFaceTable.h @@ -0,0 +1,27 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SCIIFACETABLE_H +#define SCIIFACETABLE_H + +#include "IFaceTable.h" + +extern IFaceTable SciIFaceTable; + +#endif diff --git a/src/NotepadNext/ScintillaCommenter.cpp b/src/NotepadNext/ScintillaCommenter.cpp new file mode 100644 index 000000000..69f77e65e --- /dev/null +++ b/src/NotepadNext/ScintillaCommenter.cpp @@ -0,0 +1,96 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "ScintillaCommenter.h" +#include "SelectionTracker.h" + +ScintillaCommenter::ScintillaCommenter(ScintillaNext *editor) : + editor(editor), st(editor), ua(editor) +{ +} + +void ScintillaCommenter::toggleSelection() +{ + editor->forEachLineInSelection(editor->mainSelection(), [&](int line) { + toggleLine(line); + }); +} + +void ScintillaCommenter::commentSelection() +{ + editor->forEachLineInSelection(editor->mainSelection(), [&](int line) { + commentLine(line); + }); +} + +void ScintillaCommenter::uncommentSelection() +{ + editor->forEachLineInSelection(editor->mainSelection(), [&](int line) { + uncommentLine(line); + }); +} + +void ScintillaCommenter::toggleLine(int line) +{ + auto indentPos = editor->lineIndentPosition(line); + auto lineEnd = qMin(indentPos + editor->languageSingleLineComment.length(), editor->lineEndPosition(line)); + const QByteArray commentText = editor->get_text_range(indentPos, lineEnd); + + if (commentText == editor->languageSingleLineComment) { + editor->deleteRange(indentPos, editor->languageSingleLineComment.length()); + + st.trackDeletion(indentPos, editor->languageSingleLineComment.length()); + } + else { + if (indentPos == editor->lineEndPosition(line)) { + return; + } + + editor->insertText(indentPos, editor->languageSingleLineComment.constData()); + + st.trackInsertion(indentPos, editor->languageSingleLineComment.length()); + } +} + +void ScintillaCommenter::commentLine(int line) +{ + auto indentPos = editor->lineIndentPosition(line); + + // Don't comment lines with only indentation + if (indentPos == editor->lineEndPosition(line)) { + return; + } + + editor->insertText(indentPos, editor->languageSingleLineComment.constData()); + + st.trackInsertion(indentPos, editor->languageSingleLineComment.length()); +} + +void ScintillaCommenter::uncommentLine(int line) +{ + auto indentPos = editor->lineIndentPosition(line); + auto lineEnd = qMin(indentPos + editor->languageSingleLineComment.length(), editor->lineEndPosition(line)); + const QByteArray commentText = editor->get_text_range(indentPos, lineEnd); + + if (commentText == editor->languageSingleLineComment) { + editor->deleteRange(indentPos, editor->languageSingleLineComment.length()); + + st.trackDeletion(indentPos, editor->languageSingleLineComment.length()); + } +} diff --git a/src/NotepadNext/ScintillaCommenter.h b/src/NotepadNext/ScintillaCommenter.h new file mode 100644 index 000000000..b0e949f00 --- /dev/null +++ b/src/NotepadNext/ScintillaCommenter.h @@ -0,0 +1,46 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SCINTILLACOMMENTER_H +#define SCINTILLACOMMENTER_H + +#include "ScintillaNext.h" +#include "SelectionTracker.h" +#include "UndoAction.h" + +class ScintillaCommenter +{ +public: + explicit ScintillaCommenter(ScintillaNext *editor); + + void toggleSelection(); + void commentSelection(); + void uncommentSelection(); + +private: + void toggleLine(int line); + void commentLine(int line); + void uncommentLine(int line); + + ScintillaNext *editor; + SelectionTracker st; + UndoAction ua; +}; + +#endif // SCINTILLACOMMENTER_H diff --git a/src/NotepadNext/ScintillaEnums.h b/src/NotepadNext/ScintillaEnums.h new file mode 100644 index 000000000..8f663cf55 --- /dev/null +++ b/src/NotepadNext/ScintillaEnums.h @@ -0,0 +1,1503 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */ +enum class Message { + AddText = 2001, + AddStyledText = 2002, + InsertText = 2003, + ChangeInsertion = 2672, + ClearAll = 2004, + DeleteRange = 2645, + ClearDocumentStyle = 2005, + GetLength = 2006, + GetCharAt = 2007, + GetCurrentPos = 2008, + GetAnchor = 2009, + GetStyleAt = 2010, + GetStyleIndexAt = 2038, + Redo = 2011, + SetUndoCollection = 2012, + SelectAll = 2013, + SetSavePoint = 2014, + GetStyledText = 2015, + CanRedo = 2016, + MarkerLineFromHandle = 2017, + MarkerDeleteHandle = 2018, + MarkerHandleFromLine = 2732, + MarkerNumberFromLine = 2733, + GetUndoCollection = 2019, + GetViewWS = 2020, + SetViewWS = 2021, + GetTabDrawMode = 2698, + SetTabDrawMode = 2699, + PositionFromPoint = 2022, + PositionFromPointClose = 2023, + GotoLine = 2024, + GotoPos = 2025, + SetAnchor = 2026, + GetCurLine = 2027, + GetEndStyled = 2028, + ConvertEOLs = 2029, + GetEOLMode = 2030, + SetEOLMode = 2031, + StartStyling = 2032, + SetStyling = 2033, + GetBufferedDraw = 2034, + SetBufferedDraw = 2035, + SetTabWidth = 2036, + GetTabWidth = 2121, + SetTabMinimumWidth = 2724, + GetTabMinimumWidth = 2725, + ClearTabStops = 2675, + AddTabStop = 2676, + GetNextTabStop = 2677, + SetCodePage = 2037, + SetFontLocale = 2760, + GetFontLocale = 2761, + GetIMEInteraction = 2678, + SetIMEInteraction = 2679, + MarkerDefine = 2040, + MarkerSetFore = 2041, + MarkerSetBack = 2042, + MarkerSetBackSelected = 2292, + MarkerSetForeTranslucent = 2294, + MarkerSetBackTranslucent = 2295, + MarkerSetBackSelectedTranslucent = 2296, + MarkerSetStrokeWidth = 2297, + MarkerEnableHighlight = 2293, + MarkerAdd = 2043, + MarkerDelete = 2044, + MarkerDeleteAll = 2045, + MarkerGet = 2046, + MarkerNext = 2047, + MarkerPrevious = 2048, + MarkerDefinePixmap = 2049, + MarkerAddSet = 2466, + MarkerSetAlpha = 2476, + MarkerGetLayer = 2734, + MarkerSetLayer = 2735, + SetMarginTypeN = 2240, + GetMarginTypeN = 2241, + SetMarginWidthN = 2242, + GetMarginWidthN = 2243, + SetMarginMaskN = 2244, + GetMarginMaskN = 2245, + SetMarginSensitiveN = 2246, + GetMarginSensitiveN = 2247, + SetMarginCursorN = 2248, + GetMarginCursorN = 2249, + SetMarginBackN = 2250, + GetMarginBackN = 2251, + SetMargins = 2252, + GetMargins = 2253, + StyleClearAll = 2050, + StyleSetFore = 2051, + StyleSetBack = 2052, + StyleSetBold = 2053, + StyleSetItalic = 2054, + StyleSetSize = 2055, + StyleSetFont = 2056, + StyleSetEOLFilled = 2057, + StyleResetDefault = 2058, + StyleSetUnderline = 2059, + StyleGetFore = 2481, + StyleGetBack = 2482, + StyleGetBold = 2483, + StyleGetItalic = 2484, + StyleGetSize = 2485, + StyleGetFont = 2486, + StyleGetEOLFilled = 2487, + StyleGetUnderline = 2488, + StyleGetCase = 2489, + StyleGetCharacterSet = 2490, + StyleGetVisible = 2491, + StyleGetChangeable = 2492, + StyleGetHotSpot = 2493, + StyleSetCase = 2060, + StyleSetSizeFractional = 2061, + StyleGetSizeFractional = 2062, + StyleSetWeight = 2063, + StyleGetWeight = 2064, + StyleSetCharacterSet = 2066, + StyleSetHotSpot = 2409, + StyleSetCheckMonospaced = 2254, + StyleGetCheckMonospaced = 2255, + SetElementColour = 2753, + GetElementColour = 2754, + ResetElementColour = 2755, + GetElementIsSet = 2756, + GetElementAllowsTranslucent = 2757, + GetElementBaseColour = 2758, + SetSelFore = 2067, + SetSelBack = 2068, + GetSelAlpha = 2477, + SetSelAlpha = 2478, + GetSelEOLFilled = 2479, + SetSelEOLFilled = 2480, + GetSelectionLayer = 2762, + SetSelectionLayer = 2763, + GetCaretLineLayer = 2764, + SetCaretLineLayer = 2765, + GetCaretLineHighlightSubLine = 2773, + SetCaretLineHighlightSubLine = 2774, + SetCaretFore = 2069, + AssignCmdKey = 2070, + ClearCmdKey = 2071, + ClearAllCmdKeys = 2072, + SetStylingEx = 2073, + StyleSetVisible = 2074, + GetCaretPeriod = 2075, + SetCaretPeriod = 2076, + SetWordChars = 2077, + GetWordChars = 2646, + SetCharacterCategoryOptimization = 2720, + GetCharacterCategoryOptimization = 2721, + BeginUndoAction = 2078, + EndUndoAction = 2079, + IndicSetStyle = 2080, + IndicGetStyle = 2081, + IndicSetFore = 2082, + IndicGetFore = 2083, + IndicSetUnder = 2510, + IndicGetUnder = 2511, + IndicSetHoverStyle = 2680, + IndicGetHoverStyle = 2681, + IndicSetHoverFore = 2682, + IndicGetHoverFore = 2683, + IndicSetFlags = 2684, + IndicGetFlags = 2685, + IndicSetStrokeWidth = 2751, + IndicGetStrokeWidth = 2752, + SetWhitespaceFore = 2084, + SetWhitespaceBack = 2085, + SetWhitespaceSize = 2086, + GetWhitespaceSize = 2087, + SetLineState = 2092, + GetLineState = 2093, + GetMaxLineState = 2094, + GetCaretLineVisible = 2095, + SetCaretLineVisible = 2096, + GetCaretLineBack = 2097, + SetCaretLineBack = 2098, + GetCaretLineFrame = 2704, + SetCaretLineFrame = 2705, + StyleSetChangeable = 2099, + AutoCShow = 2100, + AutoCCancel = 2101, + AutoCActive = 2102, + AutoCPosStart = 2103, + AutoCComplete = 2104, + AutoCStops = 2105, + AutoCSetSeparator = 2106, + AutoCGetSeparator = 2107, + AutoCSelect = 2108, + AutoCSetCancelAtStart = 2110, + AutoCGetCancelAtStart = 2111, + AutoCSetFillUps = 2112, + AutoCSetChooseSingle = 2113, + AutoCGetChooseSingle = 2114, + AutoCSetIgnoreCase = 2115, + AutoCGetIgnoreCase = 2116, + UserListShow = 2117, + AutoCSetAutoHide = 2118, + AutoCGetAutoHide = 2119, + AutoCSetOptions = 2638, + AutoCGetOptions = 2639, + AutoCSetDropRestOfWord = 2270, + AutoCGetDropRestOfWord = 2271, + RegisterImage = 2405, + ClearRegisteredImages = 2408, + AutoCGetTypeSeparator = 2285, + AutoCSetTypeSeparator = 2286, + AutoCSetMaxWidth = 2208, + AutoCGetMaxWidth = 2209, + AutoCSetMaxHeight = 2210, + AutoCGetMaxHeight = 2211, + SetIndent = 2122, + GetIndent = 2123, + SetUseTabs = 2124, + GetUseTabs = 2125, + SetLineIndentation = 2126, + GetLineIndentation = 2127, + GetLineIndentPosition = 2128, + GetColumn = 2129, + CountCharacters = 2633, + CountCodeUnits = 2715, + SetHScrollBar = 2130, + GetHScrollBar = 2131, + SetIndentationGuides = 2132, + GetIndentationGuides = 2133, + SetHighlightGuide = 2134, + GetHighlightGuide = 2135, + GetLineEndPosition = 2136, + GetCodePage = 2137, + GetCaretFore = 2138, + GetReadOnly = 2140, + SetCurrentPos = 2141, + SetSelectionStart = 2142, + GetSelectionStart = 2143, + SetSelectionEnd = 2144, + GetSelectionEnd = 2145, + SetEmptySelection = 2556, + SetPrintMagnification = 2146, + GetPrintMagnification = 2147, + SetPrintColourMode = 2148, + GetPrintColourMode = 2149, + FindText = 2150, + FindTextFull = 2196, + FormatRange = 2151, + FormatRangeFull = 2777, + GetFirstVisibleLine = 2152, + GetLine = 2153, + GetLineCount = 2154, + AllocateLines = 2089, + SetMarginLeft = 2155, + GetMarginLeft = 2156, + SetMarginRight = 2157, + GetMarginRight = 2158, + GetModify = 2159, + SetSel = 2160, + GetSelText = 2161, + GetTextRange = 2162, + GetTextRangeFull = 2039, + HideSelection = 2163, + PointXFromPosition = 2164, + PointYFromPosition = 2165, + LineFromPosition = 2166, + PositionFromLine = 2167, + LineScroll = 2168, + ScrollCaret = 2169, + ScrollRange = 2569, + ReplaceSel = 2170, + SetReadOnly = 2171, + Null = 2172, + CanPaste = 2173, + CanUndo = 2174, + EmptyUndoBuffer = 2175, + Undo = 2176, + Cut = 2177, + Copy = 2178, + Paste = 2179, + Clear = 2180, + SetText = 2181, + GetText = 2182, + GetTextLength = 2183, + GetDirectFunction = 2184, + GetDirectStatusFunction = 2772, + GetDirectPointer = 2185, + SetOvertype = 2186, + GetOvertype = 2187, + SetCaretWidth = 2188, + GetCaretWidth = 2189, + SetTargetStart = 2190, + GetTargetStart = 2191, + SetTargetStartVirtualSpace = 2728, + GetTargetStartVirtualSpace = 2729, + SetTargetEnd = 2192, + GetTargetEnd = 2193, + SetTargetEndVirtualSpace = 2730, + GetTargetEndVirtualSpace = 2731, + SetTargetRange = 2686, + GetTargetText = 2687, + TargetFromSelection = 2287, + TargetWholeDocument = 2690, + ReplaceTarget = 2194, + ReplaceTargetRE = 2195, + SearchInTarget = 2197, + SetSearchFlags = 2198, + GetSearchFlags = 2199, + CallTipShow = 2200, + CallTipCancel = 2201, + CallTipActive = 2202, + CallTipPosStart = 2203, + CallTipSetPosStart = 2214, + CallTipSetHlt = 2204, + CallTipSetBack = 2205, + CallTipSetFore = 2206, + CallTipSetForeHlt = 2207, + CallTipUseStyle = 2212, + CallTipSetPosition = 2213, + VisibleFromDocLine = 2220, + DocLineFromVisible = 2221, + WrapCount = 2235, + SetFoldLevel = 2222, + GetFoldLevel = 2223, + GetLastChild = 2224, + GetFoldParent = 2225, + ShowLines = 2226, + HideLines = 2227, + GetLineVisible = 2228, + GetAllLinesVisible = 2236, + SetFoldExpanded = 2229, + GetFoldExpanded = 2230, + ToggleFold = 2231, + ToggleFoldShowText = 2700, + FoldDisplayTextSetStyle = 2701, + FoldDisplayTextGetStyle = 2707, + SetDefaultFoldDisplayText = 2722, + GetDefaultFoldDisplayText = 2723, + FoldLine = 2237, + FoldChildren = 2238, + ExpandChildren = 2239, + FoldAll = 2662, + EnsureVisible = 2232, + SetAutomaticFold = 2663, + GetAutomaticFold = 2664, + SetFoldFlags = 2233, + EnsureVisibleEnforcePolicy = 2234, + SetTabIndents = 2260, + GetTabIndents = 2261, + SetBackSpaceUnIndents = 2262, + GetBackSpaceUnIndents = 2263, + SetMouseDwellTime = 2264, + GetMouseDwellTime = 2265, + WordStartPosition = 2266, + WordEndPosition = 2267, + IsRangeWord = 2691, + SetIdleStyling = 2692, + GetIdleStyling = 2693, + SetWrapMode = 2268, + GetWrapMode = 2269, + SetWrapVisualFlags = 2460, + GetWrapVisualFlags = 2461, + SetWrapVisualFlagsLocation = 2462, + GetWrapVisualFlagsLocation = 2463, + SetWrapStartIndent = 2464, + GetWrapStartIndent = 2465, + SetWrapIndentMode = 2472, + GetWrapIndentMode = 2473, + SetLayoutCache = 2272, + GetLayoutCache = 2273, + SetScrollWidth = 2274, + GetScrollWidth = 2275, + SetScrollWidthTracking = 2516, + GetScrollWidthTracking = 2517, + TextWidth = 2276, + SetEndAtLastLine = 2277, + GetEndAtLastLine = 2278, + TextHeight = 2279, + SetVScrollBar = 2280, + GetVScrollBar = 2281, + AppendText = 2282, + GetPhasesDraw = 2673, + SetPhasesDraw = 2674, + SetFontQuality = 2611, + GetFontQuality = 2612, + SetFirstVisibleLine = 2613, + SetMultiPaste = 2614, + GetMultiPaste = 2615, + GetTag = 2616, + LinesJoin = 2288, + LinesSplit = 2289, + SetFoldMarginColour = 2290, + SetFoldMarginHiColour = 2291, + SetAccessibility = 2702, + GetAccessibility = 2703, + LineDown = 2300, + LineDownExtend = 2301, + LineUp = 2302, + LineUpExtend = 2303, + CharLeft = 2304, + CharLeftExtend = 2305, + CharRight = 2306, + CharRightExtend = 2307, + WordLeft = 2308, + WordLeftExtend = 2309, + WordRight = 2310, + WordRightExtend = 2311, + Home = 2312, + HomeExtend = 2313, + LineEnd = 2314, + LineEndExtend = 2315, + DocumentStart = 2316, + DocumentStartExtend = 2317, + DocumentEnd = 2318, + DocumentEndExtend = 2319, + PageUp = 2320, + PageUpExtend = 2321, + PageDown = 2322, + PageDownExtend = 2323, + EditToggleOvertype = 2324, + Cancel = 2325, + DeleteBack = 2326, + Tab = 2327, + BackTab = 2328, + NewLine = 2329, + FormFeed = 2330, + VCHome = 2331, + VCHomeExtend = 2332, + ZoomIn = 2333, + ZoomOut = 2334, + DelWordLeft = 2335, + DelWordRight = 2336, + DelWordRightEnd = 2518, + LineCut = 2337, + LineDelete = 2338, + LineTranspose = 2339, + LineReverse = 2354, + LineDuplicate = 2404, + LowerCase = 2340, + UpperCase = 2341, + LineScrollDown = 2342, + LineScrollUp = 2343, + DeleteBackNotLine = 2344, + HomeDisplay = 2345, + HomeDisplayExtend = 2346, + LineEndDisplay = 2347, + LineEndDisplayExtend = 2348, + HomeWrap = 2349, + HomeWrapExtend = 2450, + LineEndWrap = 2451, + LineEndWrapExtend = 2452, + VCHomeWrap = 2453, + VCHomeWrapExtend = 2454, + LineCopy = 2455, + MoveCaretInsideView = 2401, + LineLength = 2350, + BraceHighlight = 2351, + BraceHighlightIndicator = 2498, + BraceBadLight = 2352, + BraceBadLightIndicator = 2499, + BraceMatch = 2353, + BraceMatchNext = 2369, + GetViewEOL = 2355, + SetViewEOL = 2356, + GetDocPointer = 2357, + SetDocPointer = 2358, + SetModEventMask = 2359, + GetEdgeColumn = 2360, + SetEdgeColumn = 2361, + GetEdgeMode = 2362, + SetEdgeMode = 2363, + GetEdgeColour = 2364, + SetEdgeColour = 2365, + MultiEdgeAddLine = 2694, + MultiEdgeClearAll = 2695, + GetMultiEdgeColumn = 2749, + SearchAnchor = 2366, + SearchNext = 2367, + SearchPrev = 2368, + LinesOnScreen = 2370, + UsePopUp = 2371, + SelectionIsRectangle = 2372, + SetZoom = 2373, + GetZoom = 2374, + CreateDocument = 2375, + AddRefDocument = 2376, + ReleaseDocument = 2377, + GetDocumentOptions = 2379, + GetModEventMask = 2378, + SetCommandEvents = 2717, + GetCommandEvents = 2718, + SetFocus = 2380, + GetFocus = 2381, + SetStatus = 2382, + GetStatus = 2383, + SetMouseDownCaptures = 2384, + GetMouseDownCaptures = 2385, + SetMouseWheelCaptures = 2696, + GetMouseWheelCaptures = 2697, + SetCursor = 2386, + GetCursor = 2387, + SetControlCharSymbol = 2388, + GetControlCharSymbol = 2389, + WordPartLeft = 2390, + WordPartLeftExtend = 2391, + WordPartRight = 2392, + WordPartRightExtend = 2393, + SetVisiblePolicy = 2394, + DelLineLeft = 2395, + DelLineRight = 2396, + SetXOffset = 2397, + GetXOffset = 2398, + ChooseCaretX = 2399, + GrabFocus = 2400, + SetXCaretPolicy = 2402, + SetYCaretPolicy = 2403, + SetPrintWrapMode = 2406, + GetPrintWrapMode = 2407, + SetHotspotActiveFore = 2410, + GetHotspotActiveFore = 2494, + SetHotspotActiveBack = 2411, + GetHotspotActiveBack = 2495, + SetHotspotActiveUnderline = 2412, + GetHotspotActiveUnderline = 2496, + SetHotspotSingleLine = 2421, + GetHotspotSingleLine = 2497, + ParaDown = 2413, + ParaDownExtend = 2414, + ParaUp = 2415, + ParaUpExtend = 2416, + PositionBefore = 2417, + PositionAfter = 2418, + PositionRelative = 2670, + PositionRelativeCodeUnits = 2716, + CopyRange = 2419, + CopyText = 2420, + SetSelectionMode = 2422, + GetSelectionMode = 2423, + GetMoveExtendsSelection = 2706, + GetLineSelStartPosition = 2424, + GetLineSelEndPosition = 2425, + LineDownRectExtend = 2426, + LineUpRectExtend = 2427, + CharLeftRectExtend = 2428, + CharRightRectExtend = 2429, + HomeRectExtend = 2430, + VCHomeRectExtend = 2431, + LineEndRectExtend = 2432, + PageUpRectExtend = 2433, + PageDownRectExtend = 2434, + StutteredPageUp = 2435, + StutteredPageUpExtend = 2436, + StutteredPageDown = 2437, + StutteredPageDownExtend = 2438, + WordLeftEnd = 2439, + WordLeftEndExtend = 2440, + WordRightEnd = 2441, + WordRightEndExtend = 2442, + SetWhitespaceChars = 2443, + GetWhitespaceChars = 2647, + SetPunctuationChars = 2648, + GetPunctuationChars = 2649, + SetCharsDefault = 2444, + AutoCGetCurrent = 2445, + AutoCGetCurrentText = 2610, + AutoCSetCaseInsensitiveBehaviour = 2634, + AutoCGetCaseInsensitiveBehaviour = 2635, + AutoCSetMulti = 2636, + AutoCGetMulti = 2637, + AutoCSetOrder = 2660, + AutoCGetOrder = 2661, + Allocate = 2446, + TargetAsUTF8 = 2447, + SetLengthForEncode = 2448, + EncodedFromUTF8 = 2449, + FindColumn = 2456, + GetCaretSticky = 2457, + SetCaretSticky = 2458, + ToggleCaretSticky = 2459, + SetPasteConvertEndings = 2467, + GetPasteConvertEndings = 2468, + ReplaceRectangular = 2771, + SelectionDuplicate = 2469, + SetCaretLineBackAlpha = 2470, + GetCaretLineBackAlpha = 2471, + SetCaretStyle = 2512, + GetCaretStyle = 2513, + SetIndicatorCurrent = 2500, + GetIndicatorCurrent = 2501, + SetIndicatorValue = 2502, + GetIndicatorValue = 2503, + IndicatorFillRange = 2504, + IndicatorClearRange = 2505, + IndicatorAllOnFor = 2506, + IndicatorValueAt = 2507, + IndicatorStart = 2508, + IndicatorEnd = 2509, + SetPositionCache = 2514, + GetPositionCache = 2515, + SetLayoutThreads = 2775, + GetLayoutThreads = 2776, + CopyAllowLine = 2519, + GetCharacterPointer = 2520, + GetRangePointer = 2643, + GetGapPosition = 2644, + IndicSetAlpha = 2523, + IndicGetAlpha = 2524, + IndicSetOutlineAlpha = 2558, + IndicGetOutlineAlpha = 2559, + SetExtraAscent = 2525, + GetExtraAscent = 2526, + SetExtraDescent = 2527, + GetExtraDescent = 2528, + MarkerSymbolDefined = 2529, + MarginSetText = 2530, + MarginGetText = 2531, + MarginSetStyle = 2532, + MarginGetStyle = 2533, + MarginSetStyles = 2534, + MarginGetStyles = 2535, + MarginTextClearAll = 2536, + MarginSetStyleOffset = 2537, + MarginGetStyleOffset = 2538, + SetMarginOptions = 2539, + GetMarginOptions = 2557, + AnnotationSetText = 2540, + AnnotationGetText = 2541, + AnnotationSetStyle = 2542, + AnnotationGetStyle = 2543, + AnnotationSetStyles = 2544, + AnnotationGetStyles = 2545, + AnnotationGetLines = 2546, + AnnotationClearAll = 2547, + AnnotationSetVisible = 2548, + AnnotationGetVisible = 2549, + AnnotationSetStyleOffset = 2550, + AnnotationGetStyleOffset = 2551, + ReleaseAllExtendedStyles = 2552, + AllocateExtendedStyles = 2553, + AddUndoAction = 2560, + CharPositionFromPoint = 2561, + CharPositionFromPointClose = 2562, + SetMouseSelectionRectangularSwitch = 2668, + GetMouseSelectionRectangularSwitch = 2669, + SetMultipleSelection = 2563, + GetMultipleSelection = 2564, + SetAdditionalSelectionTyping = 2565, + GetAdditionalSelectionTyping = 2566, + SetAdditionalCaretsBlink = 2567, + GetAdditionalCaretsBlink = 2568, + SetAdditionalCaretsVisible = 2608, + GetAdditionalCaretsVisible = 2609, + GetSelections = 2570, + GetSelectionEmpty = 2650, + ClearSelections = 2571, + SetSelection = 2572, + AddSelection = 2573, + DropSelectionN = 2671, + SetMainSelection = 2574, + GetMainSelection = 2575, + SetSelectionNCaret = 2576, + GetSelectionNCaret = 2577, + SetSelectionNAnchor = 2578, + GetSelectionNAnchor = 2579, + SetSelectionNCaretVirtualSpace = 2580, + GetSelectionNCaretVirtualSpace = 2581, + SetSelectionNAnchorVirtualSpace = 2582, + GetSelectionNAnchorVirtualSpace = 2583, + SetSelectionNStart = 2584, + GetSelectionNStart = 2585, + GetSelectionNStartVirtualSpace = 2726, + SetSelectionNEnd = 2586, + GetSelectionNEndVirtualSpace = 2727, + GetSelectionNEnd = 2587, + SetRectangularSelectionCaret = 2588, + GetRectangularSelectionCaret = 2589, + SetRectangularSelectionAnchor = 2590, + GetRectangularSelectionAnchor = 2591, + SetRectangularSelectionCaretVirtualSpace = 2592, + GetRectangularSelectionCaretVirtualSpace = 2593, + SetRectangularSelectionAnchorVirtualSpace = 2594, + GetRectangularSelectionAnchorVirtualSpace = 2595, + SetVirtualSpaceOptions = 2596, + GetVirtualSpaceOptions = 2597, + SetRectangularSelectionModifier = 2598, + GetRectangularSelectionModifier = 2599, + SetAdditionalSelFore = 2600, + SetAdditionalSelBack = 2601, + SetAdditionalSelAlpha = 2602, + GetAdditionalSelAlpha = 2603, + SetAdditionalCaretFore = 2604, + GetAdditionalCaretFore = 2605, + RotateSelection = 2606, + SwapMainAnchorCaret = 2607, + MultipleSelectAddNext = 2688, + MultipleSelectAddEach = 2689, + ChangeLexerState = 2617, + ContractedFoldNext = 2618, + VerticalCentreCaret = 2619, + MoveSelectedLinesUp = 2620, + MoveSelectedLinesDown = 2621, + SetIdentifier = 2622, + GetIdentifier = 2623, + RGBAImageSetWidth = 2624, + RGBAImageSetHeight = 2625, + RGBAImageSetScale = 2651, + MarkerDefineRGBAImage = 2626, + RegisterRGBAImage = 2627, + ScrollToStart = 2628, + ScrollToEnd = 2629, + SetTechnology = 2630, + GetTechnology = 2631, + CreateLoader = 2632, + FindIndicatorShow = 2640, + FindIndicatorFlash = 2641, + FindIndicatorHide = 2642, + VCHomeDisplay = 2652, + VCHomeDisplayExtend = 2653, + GetCaretLineVisibleAlways = 2654, + SetCaretLineVisibleAlways = 2655, + SetLineEndTypesAllowed = 2656, + GetLineEndTypesAllowed = 2657, + GetLineEndTypesActive = 2658, + SetRepresentation = 2665, + GetRepresentation = 2666, + ClearRepresentation = 2667, + ClearAllRepresentations = 2770, + SetRepresentationAppearance = 2766, + GetRepresentationAppearance = 2767, + SetRepresentationColour = 2768, + GetRepresentationColour = 2769, + EOLAnnotationSetText = 2740, + EOLAnnotationGetText = 2741, + EOLAnnotationSetStyle = 2742, + EOLAnnotationGetStyle = 2743, + EOLAnnotationClearAll = 2744, + EOLAnnotationSetVisible = 2745, + EOLAnnotationGetVisible = 2746, + EOLAnnotationSetStyleOffset = 2747, + EOLAnnotationGetStyleOffset = 2748, + SupportsFeature = 2750, + GetLineCharacterIndex = 2710, + AllocateLineCharacterIndex = 2711, + ReleaseLineCharacterIndex = 2712, + LineFromIndexPosition = 2713, + IndexPositionFromLine = 2714, + StartRecord = 3001, + StopRecord = 3002, + GetLexer = 4002, + Colourise = 4003, + SetProperty = 4004, + SetKeyWords = 4005, + GetProperty = 4008, + GetPropertyExpanded = 4009, + GetPropertyInt = 4010, + GetLexerLanguage = 4012, + PrivateLexerCall = 4013, + PropertyNames = 4014, + PropertyType = 4015, + DescribeProperty = 4016, + DescribeKeyWordSets = 4017, + GetLineEndTypesSupported = 4018, + AllocateSubStyles = 4020, + GetSubStylesStart = 4021, + GetSubStylesLength = 4022, + GetStyleFromSubStyle = 4027, + GetPrimaryStyleFromStyle = 4028, + FreeSubStyles = 4023, + SetIdentifiers = 4024, + DistanceToSecondaryStyles = 4025, + GetSubStyleBases = 4026, + GetNamedStyles = 4029, + NameOfStyle = 4030, + TagsOfStyle = 4031, + DescriptionOfStyle = 4032, + SetILexer = 4033, + GetBidirectional = 2708, + SetBidirectional = 2709, +}; +Q_ENUM(Message); + +enum class WhiteSpace { + Invisible = 0, + VisibleAlways = 1, + VisibleAfterIndent = 2, + VisibleOnlyInIndent = 3, +}; +Q_ENUM(WhiteSpace); + +enum class TabDrawMode { + LongArrow = 0, + StrikeOut = 1, +}; +Q_ENUM(TabDrawMode); + +enum class EndOfLine { + CrLf = 0, + Cr = 1, + Lf = 2, +}; +Q_ENUM(EndOfLine); + +enum class IMEInteraction { + Windowed = 0, + Inline = 1, +}; +Q_ENUM(IMEInteraction); + +enum class Alpha { + Transparent = 0, + Opaque = 255, + NoAlpha = 256, +}; +Q_ENUM(Alpha); + +enum class CursorShape { + Normal = -1, + Arrow = 2, + Wait = 4, + ReverseArrow = 7, +}; +Q_ENUM(CursorShape); + +enum class MarkerSymbol { + Circle = 0, + RoundRect = 1, + Arrow = 2, + SmallRect = 3, + ShortArrow = 4, + Empty = 5, + ArrowDown = 6, + Minus = 7, + Plus = 8, + VLine = 9, + LCorner = 10, + TCorner = 11, + BoxPlus = 12, + BoxPlusConnected = 13, + BoxMinus = 14, + BoxMinusConnected = 15, + LCornerCurve = 16, + TCornerCurve = 17, + CirclePlus = 18, + CirclePlusConnected = 19, + CircleMinus = 20, + CircleMinusConnected = 21, + Background = 22, + DotDotDot = 23, + Arrows = 24, + Pixmap = 25, + FullRect = 26, + LeftRect = 27, + Available = 28, + Underline = 29, + RgbaImage = 30, + Bookmark = 31, + VerticalBookmark = 32, + Character = 10000, +}; +Q_ENUM(MarkerSymbol); + +enum class MarkerOutline { + FolderEnd = 25, + FolderOpenMid = 26, + FolderMidTail = 27, + FolderTail = 28, + FolderSub = 29, + Folder = 30, + FolderOpen = 31, +}; +Q_ENUM(MarkerOutline); + +enum class MarginType { + Symbol = 0, + Number = 1, + Back = 2, + Fore = 3, + Text = 4, + RText = 5, + Colour = 6, +}; +Q_ENUM(MarginType); + +enum class StylesCommon { + Default = 32, + LineNumber = 33, + BraceLight = 34, + BraceBad = 35, + ControlChar = 36, + IndentGuide = 37, + CallTip = 38, + FoldDisplayText = 39, + LastPredefined = 39, + Max = 255, +}; +Q_ENUM(StylesCommon); + +enum class CharacterSet { + Ansi = 0, + Default = 1, + Baltic = 186, + ChineseBig5 = 136, + EastEurope = 238, + GB2312 = 134, + Greek = 161, + Hangul = 129, + Mac = 77, + Oem = 255, + Russian = 204, + Oem866 = 866, + Cyrillic = 1251, + ShiftJis = 128, + Symbol = 2, + Turkish = 162, + Johab = 130, + Hebrew = 177, + Arabic = 178, + Vietnamese = 163, + Thai = 222, + Iso8859_15 = 1000, +}; +Q_ENUM(CharacterSet); + +enum class CaseVisible { + Mixed = 0, + Upper = 1, + Lower = 2, + Camel = 3, +}; +Q_ENUM(CaseVisible); + +enum class FontWeight { + Normal = 400, + SemiBold = 600, + Bold = 700, +}; +Q_ENUM(FontWeight); + +enum class Element { + List = 0, + ListBack = 1, + ListSelected = 2, + ListSelectedBack = 3, + SelectionText = 10, + SelectionBack = 11, + SelectionAdditionalText = 12, + SelectionAdditionalBack = 13, + SelectionSecondaryText = 14, + SelectionSecondaryBack = 15, + SelectionInactiveText = 16, + SelectionInactiveBack = 17, + Caret = 40, + CaretAdditional = 41, + CaretLineBack = 50, + WhiteSpace = 60, + WhiteSpaceBack = 61, + HotSpotActive = 70, + HotSpotActiveBack = 71, + FoldLine = 80, + HiddenLine = 81, +}; +Q_ENUM(Element); + +enum class Layer { + Base = 0, + UnderText = 1, + OverText = 2, +}; +Q_ENUM(Layer); + +enum class IndicatorStyle { + Plain = 0, + Squiggle = 1, + TT = 2, + Diagonal = 3, + Strike = 4, + Hidden = 5, + Box = 6, + RoundBox = 7, + StraightBox = 8, + Dash = 9, + Dots = 10, + SquiggleLow = 11, + DotBox = 12, + SquigglePixmap = 13, + CompositionThick = 14, + CompositionThin = 15, + FullBox = 16, + TextFore = 17, + Point = 18, + PointCharacter = 19, + Gradient = 20, + GradientCentre = 21, +}; +Q_ENUM(IndicatorStyle); + +enum class IndicatorNumbers { + Container = 8, + Ime = 32, + ImeMax = 35, + Max = 35, +}; +Q_ENUM(IndicatorNumbers); + +enum class IndicValue { + Bit = 0x1000000, + Mask = 0xFFFFFF, +}; +Q_ENUM(IndicValue); + +enum class IndicFlag { + None = 0, + ValueFore = 1, +}; +Q_ENUM(IndicFlag); + +enum class AutoCompleteOption { + Normal = 0, + FixedSize = 1, +}; +Q_ENUM(AutoCompleteOption); + +enum class IndentView { + None = 0, + Real = 1, + LookForward = 2, + LookBoth = 3, +}; +Q_ENUM(IndentView); + +enum class PrintOption { + Normal = 0, + InvertLight = 1, + BlackOnWhite = 2, + ColourOnWhite = 3, + ColourOnWhiteDefaultBG = 4, + ScreenColours = 5, +}; +Q_ENUM(PrintOption); + +enum class FindOption { + None = 0x0, + WholeWord = 0x2, + MatchCase = 0x4, + WordStart = 0x00100000, + RegExp = 0x00200000, + Posix = 0x00400000, + Cxx11RegEx = 0x00800000, +}; +Q_ENUM(FindOption); + +enum class FoldLevel { + None = 0x0, + Base = 0x400, + WhiteFlag = 0x1000, + HeaderFlag = 0x2000, + NumberMask = 0x0FFF, +}; +Q_ENUM(FoldLevel); + +enum class FoldDisplayTextStyle { + Hidden = 0, + Standard = 1, + Boxed = 2, +}; +Q_ENUM(FoldDisplayTextStyle); + +enum class FoldAction { + Contract = 0, + Expand = 1, + Toggle = 2, +}; +Q_ENUM(FoldAction); + +enum class AutomaticFold { + None = 0x0000, + Show = 0x0001, + Click = 0x0002, + Change = 0x0004, +}; +Q_ENUM(AutomaticFold); + +enum class FoldFlag { + None = 0x0000, + LineBeforeExpanded = 0x0002, + LineBeforeContracted = 0x0004, + LineAfterExpanded = 0x0008, + LineAfterContracted = 0x0010, + LevelNumbers = 0x0040, + LineState = 0x0080, +}; +Q_ENUM(FoldFlag); + +enum class IdleStyling { + None = 0, + ToVisible = 1, + AfterVisible = 2, + All = 3, +}; +Q_ENUM(IdleStyling); + +enum class Wrap { + None = 0, + Word = 1, + Char = 2, + WhiteSpace = 3, +}; +Q_ENUM(Wrap); + +enum class WrapVisualFlag { + None = 0x0000, + End = 0x0001, + Start = 0x0002, + Margin = 0x0004, +}; +Q_ENUM(WrapVisualFlag); + +enum class WrapVisualLocation { + Default = 0x0000, + EndByText = 0x0001, + StartByText = 0x0002, +}; +Q_ENUM(WrapVisualLocation); + +enum class WrapIndentMode { + Fixed = 0, + Same = 1, + Indent = 2, + DeepIndent = 3, +}; +Q_ENUM(WrapIndentMode); + +enum class LineCache { + None = 0, + Caret = 1, + Page = 2, + Document = 3, +}; +Q_ENUM(LineCache); + +enum class PhasesDraw { + One = 0, + Two = 1, + Multiple = 2, +}; +Q_ENUM(PhasesDraw); + +enum class FontQuality { + QualityMask = 0xF, + QualityDefault = 0, + QualityNonAntialiased = 1, + QualityAntialiased = 2, + QualityLcdOptimized = 3, +}; +Q_ENUM(FontQuality); + +enum class MultiPaste { + Once = 0, + Each = 1, +}; +Q_ENUM(MultiPaste); + +enum class Accessibility { + Disabled = 0, + Enabled = 1, +}; +Q_ENUM(Accessibility); + +enum class EdgeVisualStyle { + None = 0, + Line = 1, + Background = 2, + MultiLine = 3, +}; +Q_ENUM(EdgeVisualStyle); + +enum class PopUp { + Never = 0, + All = 1, + Text = 2, +}; +Q_ENUM(PopUp); + +enum class DocumentOption { + Default = 0, + StylesNone = 0x1, + TextLarge = 0x100, +}; +Q_ENUM(DocumentOption); + +enum class Status { + Ok = 0, + Failure = 1, + BadAlloc = 2, + WarnStart = 1000, + RegEx = 1001, +}; +Q_ENUM(Status); + +enum class VisiblePolicy { + Slop = 0x01, + Strict = 0x04, +}; +Q_ENUM(VisiblePolicy); + +enum class CaretPolicy { + Slop = 0x01, + Strict = 0x04, + Jumps = 0x10, + Even = 0x08, +}; +Q_ENUM(CaretPolicy); + +enum class SelectionMode { + Stream = 0, + Rectangle = 1, + Lines = 2, + Thin = 3, +}; +Q_ENUM(SelectionMode); + +enum class CaseInsensitiveBehaviour { + RespectCase = 0, + IgnoreCase = 1, +}; +Q_ENUM(CaseInsensitiveBehaviour); + +enum class MultiAutoComplete { + Once = 0, + Each = 1, +}; +Q_ENUM(MultiAutoComplete); + +enum class Ordering { + PreSorted = 0, + PerformSort = 1, + Custom = 2, +}; +Q_ENUM(Ordering); + +enum class CaretSticky { + Off = 0, + On = 1, + WhiteSpace = 2, +}; +Q_ENUM(CaretSticky); + +enum class CaretStyle { + Invisible = 0, + Line = 1, + Block = 2, + OverstrikeBar = 0, + OverstrikeBlock = 0x10, + Curses = 0x20, + InsMask = 0xF, + BlockAfter = 0x100, +}; +Q_ENUM(CaretStyle); + +enum class MarginOption { + None = 0, + SubLineSelect = 1, +}; +Q_ENUM(MarginOption); + +enum class AnnotationVisible { + Hidden = 0, + Standard = 1, + Boxed = 2, + Indented = 3, +}; +Q_ENUM(AnnotationVisible); + +enum class UndoFlags { + None = 0, + MayCoalesce = 1, +}; +Q_ENUM(UndoFlags); + +enum class VirtualSpace { + None = 0, + RectangularSelection = 1, + UserAccessible = 2, + NoWrapLineStart = 4, +}; +Q_ENUM(VirtualSpace); + +enum class Technology { + Default = 0, + DirectWrite = 1, + DirectWriteRetain = 2, + DirectWriteDC = 3, +}; +Q_ENUM(Technology); + +enum class LineEndType { + Default = 0, + Unicode = 1, +}; +Q_ENUM(LineEndType); + +enum class RepresentationAppearance { + Plain = 0, + Blob = 1, + Colour = 0x10, +}; +Q_ENUM(RepresentationAppearance); + +enum class EOLAnnotationVisible { + Hidden = 0x0, + Standard = 0x1, + Boxed = 0x2, + Stadium = 0x100, + FlatCircle = 0x101, + AngleCircle = 0x102, + CircleFlat = 0x110, + Flats = 0x111, + AngleFlat = 0x112, + CircleAngle = 0x120, + FlatAngle = 0x121, + Angles = 0x122, +}; +Q_ENUM(EOLAnnotationVisible); + +enum class Supports { + LineDrawsFinal = 0, + PixelDivisions = 1, + FractionalStrokeWidth = 2, + TranslucentStroke = 3, + PixelModification = 4, + ThreadSafeMeasureWidths = 5, +}; +Q_ENUM(Supports); + +enum class LineCharacterIndexType { + None = 0, + Utf32 = 1, + Utf16 = 2, +}; +Q_ENUM(LineCharacterIndexType); + +enum class TypeProperty { + Boolean = 0, + Integer = 1, + String = 2, +}; +Q_ENUM(TypeProperty); + +enum class ModificationFlags { + None = 0x0, + InsertText = 0x1, + DeleteText = 0x2, + ChangeStyle = 0x4, + ChangeFold = 0x8, + User = 0x10, + Undo = 0x20, + Redo = 0x40, + MultiStepUndoRedo = 0x80, + LastStepInUndoRedo = 0x100, + ChangeMarker = 0x200, + BeforeInsert = 0x400, + BeforeDelete = 0x800, + MultilineUndoRedo = 0x1000, + StartAction = 0x2000, + ChangeIndicator = 0x4000, + ChangeLineState = 0x8000, + ChangeMargin = 0x10000, + ChangeAnnotation = 0x20000, + Container = 0x40000, + LexerState = 0x80000, + InsertCheck = 0x100000, + ChangeTabStops = 0x200000, + ChangeEOLAnnotation = 0x400000, + EventMaskAll = 0x7FFFFF, +}; +Q_ENUM(ModificationFlags); + +enum class Update { + None = 0x0, + Content = 0x1, + Selection = 0x2, + VScroll = 0x4, + HScroll = 0x8, +}; +Q_ENUM(Update); + +enum class FocusChange { + Change = 768, + Setfocus = 512, + Killfocus = 256, +}; +Q_ENUM(FocusChange); + +enum class Keys { + Down = 300, + Up = 301, + Left = 302, + Right = 303, + Home = 304, + End = 305, + Prior = 306, + Next = 307, + Delete = 308, + Insert = 309, + Escape = 7, + Back = 8, + Tab = 9, + Return = 13, + Add = 310, + Subtract = 311, + Divide = 312, + Win = 313, + RWin = 314, + Menu = 315, +}; +Q_ENUM(Keys); + +enum class KeyMod { + Norm = 0, + Shift = 1, + Ctrl = 2, + Alt = 4, + Super = 8, + Meta = 16, +}; +Q_ENUM(KeyMod); + +enum class CompletionMethods { + FillUp = 1, + DoubleClick = 2, + Tab = 3, + Newline = 4, + Command = 5, +}; +Q_ENUM(CompletionMethods); + +enum class CharacterSource { + DirectInput = 0, + TentativeInput = 1, + ImeResult = 2, +}; +Q_ENUM(CharacterSource); + +enum class Bidirectional { + Disabled = 0, + L2R = 1, + R2L = 2, +}; +Q_ENUM(Bidirectional); + +enum class Notification { + StyleNeeded = 2000, + CharAdded = 2001, + SavePointReached = 2002, + SavePointLeft = 2003, + ModifyAttemptRO = 2004, + Key = 2005, + DoubleClick = 2006, + UpdateUI = 2007, + Modified = 2008, + MacroRecord = 2009, + MarginClick = 2010, + NeedShown = 2011, + Painted = 2013, + UserListSelection = 2014, + URIDropped = 2015, + DwellStart = 2016, + DwellEnd = 2017, + Zoom = 2018, + HotSpotClick = 2019, + HotSpotDoubleClick = 2020, + CallTipClick = 2021, + AutoCSelection = 2022, + IndicatorClick = 2023, + IndicatorRelease = 2024, + AutoCCancelled = 2025, + AutoCCharDeleted = 2026, + HotSpotReleaseClick = 2027, + FocusIn = 2028, + FocusOut = 2029, + AutoCCompleted = 2030, + MarginRightClick = 2031, + AutoCSelectionChange = 2032, +}; +Q_ENUM(Notification); +/* --Autogenerated -- end of section automatically generated from Scintilla.iface */ diff --git a/src/NotepadNext/ScintillaNext.cpp b/src/NotepadNext/ScintillaNext.cpp new file mode 100644 index 000000000..761a3eb6a --- /dev/null +++ b/src/NotepadNext/ScintillaNext.cpp @@ -0,0 +1,629 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "ScintillaNext.h" +#include "ScintillaCommenter.h" + +#include "uchardet.h" +#include + +#include +#include +#include +#include + + +const int CHUNK_SIZE = 1024 * 1024 * 4; // Not sure what is best + + +static QFileDevice::FileError writeToDisk(const QByteArray &data, const QString &path) +{ + qInfo(Q_FUNC_INFO); + + QFile file(path); + + if (file.open(QIODevice::WriteOnly)) { + if (file.write(data) != -1) { + file.close(); + return QFileDevice::NoError; + } + } + + // If it got to this point there was an error + qWarning("writeToDisk() failure code %d: %s", file.error(), qPrintable(file.errorString())); + return file.error(); +} + +static bool isNewlineCharacter(char c) +{ + return c == '\n' || c == '\r'; +} + +ScintillaNext::ScintillaNext(QString name, QWidget *parent) : + ScintillaEdit(parent), + name(name), + indicatorResources(INDICATOR_MAX + 1) +{ + // Per the scintilla documentation, some parts of the range are not generally available + indicatorResources.disableRange(0, 7); + indicatorResources.disableRange(INDICATOR_IME, INDICATOR_IME_MAX); + indicatorResources.disableRange(INDICATOR_HISTORY_REVERTED_TO_ORIGIN_INSERTION, INDICATOR_HISTORY_REVERTED_TO_MODIFIED_DELETION); +} + +ScintillaNext::~ScintillaNext() +{ +} + +ScintillaNext *ScintillaNext::fromFile(const QString &filePath, bool tryToCreate) +{ + QFile file(filePath); + ScintillaNext *editor = new ScintillaNext(file.fileName()); + + if(tryToCreate && !file.exists()) { + qInfo("Trying to create %s", qUtf8Printable(filePath)); + QDir d; + d.mkpath(QFileInfo(file).path()); + + QFile f(filePath); + f.open(QIODevice::WriteOnly); + f.close(); + } + + bool readSuccessful = editor->readFromDisk(file); + + if (!readSuccessful) { + delete editor; + return Q_NULLPTR; + } + + editor->setFileInfo(filePath); + + return editor; +} + +int ScintillaNext::allocateIndicator(const QString &name) +{ + return indicatorResources.requestResource(name); +} + +void ScintillaNext::goToRange(const Sci_CharacterRange &range) +{ + qInfo(Q_FUNC_INFO); + + if (isRangeValid(range)) { + // Lines can be folded so make sure they are visible + ensureVisible(lineFromPosition(range.cpMin)); + ensureVisible(lineFromPosition(range.cpMax)); + + setSelection(range.cpMin, range.cpMax); + scrollRange(range.cpMax, range.cpMin); + } +} + +QByteArray ScintillaNext::eolString() const +{ + const int eol = eOLMode(); + + if (eol == SC_EOL_LF) return QByteArrayLiteral("\n"); + else if (eol == SC_EOL_CRLF) return QByteArrayLiteral("\r\n"); + else return QByteArrayLiteral("\r"); +} + +bool ScintillaNext::lineIsEmpty(int line) +{ + return (lineEndPosition(line) - positionFromLine(line)) == 0; +} + +void ScintillaNext::deleteLine(int line) +{ + deleteRange(positionFromLine(line), lineLength(line)); +} + +void ScintillaNext::cutAllowLine() +{ + if (selectionEmpty()) { + copyAllowLine(); + lineDelete(); + } + else { + cut(); + } +} + +void ScintillaNext::modifyFoldLevels(int level, int action) +{ + const int totalLines = lineCount(); + + int line = 0; + while (line < totalLines) { + int foldFlags = foldLevel(line); // Even though its called fold level it contains several other flags + bool isHeader = foldFlags & SC_FOLDLEVELHEADERFLAG; + int actualLevel = (foldFlags & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE; + + if (isHeader && actualLevel == level) { + foldLine(line, action); + line = lastChild(line, -1) + 1; + } + else { + ++line; + } + } +} + +void ScintillaNext::foldAllLevels(int level) +{ + modifyFoldLevels(level, SC_FOLDACTION_CONTRACT); +} + +void ScintillaNext::unFoldAllLevels(int level) +{ + modifyFoldLevels(level, SC_FOLDACTION_EXPAND); +} + +void ScintillaNext::deleteLeadingEmptyLines() +{ + while (lineCount() > 1 && lineIsEmpty(0)) { + deleteLine(0); + } +} + +void ScintillaNext::deleteTrailingEmptyLines() +{ + const int docLength = length(); + int position = docLength; + + while (position > 0 && isNewlineCharacter(charAt(position - 1))) { + position--; + } + + deleteRange(position, docLength - position); +} + +bool ScintillaNext::isSavedToDisk() const +{ + return !canSaveToDisk(); +} + +bool ScintillaNext::canSaveToDisk() const +{ + // The buffer can be saved if: + // - It is marked as a temporary since as soon as it gets saved it is no longer a temporary buffer + // - A modified file + // - A missing file since as soon as it is saved it is no longer missing. + return temporary || + (bufferType == ScintillaNext::New && modify()) || + (bufferType == ScintillaNext::File && modify()) || + (bufferType == ScintillaNext::FileMissing); +} + +void ScintillaNext::setName(const QString &name) +{ + this->name = name; + + emit renamed(); +} + +bool ScintillaNext::isFile() const +{ + return bufferType == ScintillaNext::File || bufferType == ScintillaNext::FileMissing; +} + +QFileInfo ScintillaNext::getFileInfo() const +{ + Q_ASSERT(isFile()); + + return fileInfo; +} + +QString ScintillaNext::getPath() const +{ + Q_ASSERT(isFile()); + + return QDir::toNativeSeparators(fileInfo.canonicalPath()); +} + +QString ScintillaNext::getFilePath() const +{ + Q_ASSERT(isFile()); + + return QDir::toNativeSeparators(fileInfo.canonicalFilePath()); +} + +void ScintillaNext::setFoldMarkers(const QString &type) +{ + QMap> map{ + {"simple", {SC_MARK_MINUS, SC_MARK_PLUS, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY}}, + {"arrow", {SC_MARK_ARROWDOWN, SC_MARK_ARROW, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY}}, + {"circle", {SC_MARK_CIRCLEMINUS, SC_MARK_CIRCLEPLUS, SC_MARK_VLINE, SC_MARK_LCORNERCURVE, SC_MARK_CIRCLEPLUSCONNECTED, SC_MARK_CIRCLEMINUSCONNECTED, SC_MARK_TCORNERCURVE }}, + {"box", {SC_MARK_BOXMINUS, SC_MARK_BOXPLUS, SC_MARK_VLINE, SC_MARK_LCORNER, SC_MARK_BOXPLUSCONNECTED, SC_MARK_BOXMINUSCONNECTED, SC_MARK_TCORNER }}, + }; + + if (!map.contains(type)) + return; + + const auto types = map[type]; + markerDefine(SC_MARKNUM_FOLDEROPEN, types[0]); + markerDefine(SC_MARKNUM_FOLDER, types[1]); + markerDefine(SC_MARKNUM_FOLDERSUB, types[2]); + markerDefine(SC_MARKNUM_FOLDERTAIL, types[3]); + markerDefine(SC_MARKNUM_FOLDEREND, types[4]); + markerDefine(SC_MARKNUM_FOLDEROPENMID, types[5]); + markerDefine(SC_MARKNUM_FOLDERMIDTAIL, types[6]); +} + +void ScintillaNext::close() +{ + emit closed(); + + deleteLater(); +} + +QFileDevice::FileError ScintillaNext::save() +{ + qInfo(Q_FUNC_INFO); + + Q_ASSERT(isFile()); + + emit aboutToSave(); + + QFileDevice::FileError writeSuccessful = writeToDisk(QByteArray::fromRawData((char*)characterPointer(), textLength()), fileInfo.filePath()); + + if (writeSuccessful == QFileDevice::NoError) { + updateTimestamp(); + setSavePoint(); + + // If this was a temporary file, make sure it is not any more + setTemporary(false); + + emit saved(); + } + + return writeSuccessful; +} + +void ScintillaNext::reload() +{ + Q_ASSERT(isFile()); + + // Ensure the file still exists. + if (!QFile::exists(fileInfo.canonicalFilePath())) { + return; + } + + // Remove all the text + { + const QSignalBlocker blocker(this); + setUndoCollection(false); + emptyUndoBuffer(); + setText(""); + setUndoCollection(true); + } + + // NOTE: if the read fails then the buffer will be completely empty...which probably + // isn't a good thing, but this should be a rare occurrence. + QFile f(fileInfo.canonicalFilePath()); + bool readSuccessful = readFromDisk(f); + + if (readSuccessful) { + updateTimestamp(); + setSavePoint(); + } + + return; +} + +QFileDevice::FileError ScintillaNext::saveAs(const QString &newFilePath) +{ + bool isRenamed = bufferType == ScintillaNext::New || fileInfo.canonicalFilePath() != newFilePath; + + emit aboutToSave(); + + QFileDevice::FileError saveSuccessful = writeToDisk(QByteArray::fromRawData((char*)characterPointer(), textLength()), newFilePath); + + if (saveSuccessful == QFileDevice::NoError) { + setFileInfo(newFilePath); + setSavePoint(); + + // If this was a temporary file, make sure it is not any more + setTemporary(false); + + emit saved(); + + if (isRenamed) { + emit renamed(); + } + } + + return saveSuccessful; +} + +QFileDevice::FileError ScintillaNext::saveCopyAs(const QString &filePath) +{ + return writeToDisk(QByteArray::fromRawData((char*)characterPointer(), textLength()), filePath); +} + +bool ScintillaNext::rename(const QString &newFilePath) +{ + emit aboutToSave(); + + // Write out the buffer to the new path + if (saveCopyAs(newFilePath)) { + // Remove the old file + const QString oldPath = fileInfo.canonicalFilePath(); + QFile::remove(oldPath); + + // Everything worked fine, so update the buffer's info + setFileInfo(newFilePath); + setSavePoint(); + + // If this was a temporary file, make sure it is not any more + setTemporary(false); + + emit saved(); + + emit renamed(); + + return true; + } + + return false; +} + +ScintillaNext::FileStateChange ScintillaNext::checkFileForStateChange() +{ + if (bufferType == BufferType::New) { + return FileStateChange::NoChange; + } + else if (bufferType == BufferType::File) { + // refresh else exists() fails to notice missing file + fileInfo.refresh(); + + if (!fileInfo.exists()) { + bufferType = BufferType::FileMissing; + + emit savePointChanged(false); + + return FileStateChange::Deleted; + } + + // See if the timestamp changed + if (modifiedTime != fileTimestamp()) { + return FileStateChange::Modified; + } + else { + return FileStateChange::NoChange; + } + } + else if (bufferType == BufferType::FileMissing) { + // See if it reappeared + fileInfo.refresh(); + + if (fileInfo.exists()) { + bufferType = BufferType::File; + + return FileStateChange::Restored; + } + else { + return FileStateChange::NoChange; + } + } + + qInfo("type() = %d", bufferType); + Q_ASSERT(false); + + return FileStateChange::NoChange; +} + +bool ScintillaNext::moveToTrash() +{ + if (QFile::exists(fileInfo.canonicalFilePath())) { + QFile f(fileInfo.canonicalFilePath()); + + return f.moveToTrash(); + } + + return false; +} + +void ScintillaNext::toggleCommentSelection() +{ + ScintillaCommenter sc(this); + sc.toggleSelection(); +} + +void ScintillaNext::commentLineSelection() +{ + ScintillaCommenter sc(this); + sc.commentSelection(); +} + +void ScintillaNext::uncommentLineSelection() +{ + ScintillaCommenter sc(this); + sc.uncommentSelection(); +} + +void ScintillaNext::dragEnterEvent(QDragEnterEvent *event) +{ + // Ignore all drag and drop events with urls and let the main application handle it + if (event->mimeData()->hasUrls()) { + return; + } + + ScintillaEdit::dragEnterEvent(event); +} + +void ScintillaNext::dropEvent(QDropEvent *event) +{ + // Ignore all drag and drop events with urls and let the main application handle it + if (event->mimeData()->hasUrls()) { + return; + } + + ScintillaEdit::dropEvent(event); +} + +bool ScintillaNext::readFromDisk(QFile &file) +{ + if (!file.exists()) { + qWarning("Cannot read \"%s\": doesn't exist", qUtf8Printable(file.fileName())); + return false; + } + + if (!file.open(QIODevice::ReadOnly)) { + qWarning("QFile::open() failed when opening \"%s\" - error code %d: %s", qUtf8Printable(file.fileName()), file.error(), qUtf8Printable(file.errorString())); + return false; + } + + // TODO: figure out what to do if "size" is too big + allocate(file.size()); + + // Turn off undo collection and block signals during loading + setUndoCollection(false); + blockSignals(true); + // TODO disable notifications + // modEventMask(SC_MOD_NONE)? + + QByteArray chunk; + qint64 bytesRead; + QTextCodec *codec = Q_NULLPTR; + QTextCodec::ConverterState state; + + bool first_read = true; + do { + // Try to read as much as possible + chunk.resize(CHUNK_SIZE); + bytesRead = file.read(chunk.data(), CHUNK_SIZE); + chunk.resize(bytesRead); + + qDebug("Read %lld bytes", bytesRead); + + // TODO: this needs moved out of here. Would make much more sense to have a class (or classes) + // responsible for handling low level situations like this to do things like: + // - determine encoding + // - determine space vs tabs + // - determine indentation size + + if (first_read) { + first_read = false; + + // Search for a BOM mark + codec = QTextCodec::codecForUtfText(chunk, Q_NULLPTR); + + if (codec != Q_NULLPTR) { + qDebug("BOM mark found"); + } + else { + qDebug("BOM mark not found, using uchardet"); + + // Limit decoding to the first 64 kilobytes + int detectionSize = qMin(chunk.size(), 64 * 1024); + + // Use uchardet to try and detect file encoding since no BOM was found + uchardet_t encodingDetector = uchardet_new(); + if (uchardet_handle_data(encodingDetector, chunk.data(), detectionSize) == 0) { + uchardet_data_end(encodingDetector); + + qDebug("uchardet detected encoding as: '%s'", uchardet_get_charset(encodingDetector)); + codec = QTextCodec::codecForName(uchardet_get_charset(encodingDetector)); + } + else { + qDebug("uchardet failure"); + } + uchardet_delete(encodingDetector); + } + + qDebug("Using codec: '%s'", codec ? codec->name().constData() : ""); + } + + if (codec) { + const QByteArray utf8_data = codec->toUnicode(chunk.constData(), chunk.size(), &state).toUtf8(); + appendText(utf8_data.size(), utf8_data.constData()); + } + else { + appendText(chunk.size(), chunk.constData()); + } + } while (!file.atEnd() && status() == SC_STATUS_OK); + + file.close(); + + // Restore it back + this->blockSignals(false); + setUndoCollection(true); + // modEventMask(SC_MODEVENTMASKALL)? + + if (status() != SC_STATUS_OK) { + qWarning("something bad happened in document->add_data() %ld", status()); + return false; + } + + if (bytesRead == -1) { + qWarning("Something bad happened when reading disk %d %s", file.error(), qUtf8Printable(file.errorString())); + return false; + } + + if (!QFileInfo(file).isWritable()) { + qInfo("Setting file as read-only"); + setReadOnly(true); + } + + return true; +} + +QDateTime ScintillaNext::fileTimestamp() +{ + Q_ASSERT(bufferType != ScintillaNext::New); + + fileInfo.refresh(); + qInfo("%s last modified %s", qUtf8Printable(fileInfo.fileName()), qUtf8Printable(fileInfo.lastModified().toString())); + return fileInfo.lastModified(); +} + +void ScintillaNext::updateTimestamp() +{ + modifiedTime = fileTimestamp(); +} + +void ScintillaNext::setFileInfo(const QString &filePath) +{ + fileInfo.setFile(filePath); + fileInfo.makeAbsolute(); + + Q_ASSERT(fileInfo.exists()); + + name = fileInfo.fileName(); + bufferType = ScintillaNext::File; + + updateTimestamp(); +} + +void ScintillaNext::detachFileInfo(const QString &newName) +{ + setName(newName); + + bufferType = ScintillaNext::New; +} + +void ScintillaNext::setTemporary(bool temp) +{ + temporary = temp; + + // Fake this signal + emit savePointChanged(temporary); +} diff --git a/src/NotepadNext/ScintillaNext.h b/src/NotepadNext/ScintillaNext.h new file mode 100644 index 000000000..0eab58078 --- /dev/null +++ b/src/NotepadNext/ScintillaNext.h @@ -0,0 +1,185 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SCINTILLANEXT_H +#define SCINTILLANEXT_H + +#include "RangeAllocator.h" +#include "ScintillaEdit.h" + +#include +#include +#include + + + + +class ScintillaNext : public ScintillaEdit +{ + Q_OBJECT + +public: + static bool isRangeValid(const Sci_CharacterRange &range) + { + return range.cpMin != INVALID_POSITION && range.cpMax != INVALID_POSITION; + } + + explicit ScintillaNext(QString name, QWidget *parent = Q_NULLPTR); + virtual ~ScintillaNext(); + + static ScintillaNext *fromFile(const QString &filePath, bool tryToCreate=false); + + int allocateIndicator(const QString &name); + + template + void forEachMatch(const QString &text, Func callback) { forEachMatch(text.toUtf8(), callback); } + + template + void forEachMatch(const QByteArray &byteArray, Func callback) { forEachMatchInRange(byteArray, callback, {0, (Sci_PositionCR)length()}); } + + template + void forEachMatchInRange(const QByteArray &byteArray, Func callback, Sci_CharacterRange range); + + template + void forEachLineInSelection(int selection, Func callback); + + void goToRange(const Sci_CharacterRange &range); + + QByteArray eolString() const; + + bool lineIsEmpty(int line); + + void deleteLine(int line); + + void cutAllowLine(); + + void modifyFoldLevels(int level, int action); + void foldAllLevels(int level); + void unFoldAllLevels(int level); + + void deleteLeadingEmptyLines(); + void deleteTrailingEmptyLines(); + + bool isFile() const; + QFileInfo getFileInfo() const; + + bool isSavedToDisk() const; + bool canSaveToDisk() const; + + QString getName() const { return name; } + void setName(const QString &name); + QString getPath() const; + QString getFilePath() const; + + // NOTE: this is dangerous and should only be used in very rare situations + void setFileInfo(const QString &filePath); + + void detachFileInfo(const QString &newName); + + enum FileStateChange { + NoChange, + Modified, + Deleted, + Restored, + }; + + enum BufferType { + New, // A temporary buffer, e.g. "New 1" + File, // Buffer tied to a file on the file system + FileMissing, // Buffer with a missing file on the file system + }; + + bool isTemporary() const { return temporary; } + void setTemporary(bool temp); + + void setFoldMarkers(const QString &type); + + QString languageName; + QByteArray languageSingleLineComment; + + #include "ScintillaEnums.h" + + +public slots: + void close(); + QFileDevice::FileError save(); + void reload(); + QFileDevice::FileError saveAs(const QString &newFilePath); + QFileDevice::FileError saveCopyAs(const QString &filePath); + bool rename(const QString &newFilePath); + ScintillaNext::FileStateChange checkFileForStateChange(); + bool moveToTrash(); + + void toggleCommentSelection(); + void commentLineSelection(); + void uncommentLineSelection(); + +signals: + void aboutToSave(); + void saved(); + void closed(); + void renamed(); + + void lexerChanged(); + +protected: + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + +private: + QString name; + BufferType bufferType = BufferType::New; + QFileInfo fileInfo; + QDateTime modifiedTime; + RangeAllocator indicatorResources; + + bool temporary = false; // Temporary file loaded from a session. It can either be a 'New' file or actual 'File' + + bool readFromDisk(QFile &file); + QDateTime fileTimestamp(); + void updateTimestamp(); + +}; + +template +void ScintillaNext::forEachLineInSelection(int selection, Func callback) +{ + int lineStart = lineFromPosition(selectionNStart(selection)); + int lineEnd = lineFromPosition(selectionNEnd(selection)); + + for (int curLine = lineStart; curLine <= lineEnd; ++curLine) { + callback(curLine); + } +} + +// Stick this in the header file...because C++, that's why +template +void ScintillaNext::forEachMatchInRange(const QByteArray &text, Func callback, Sci_CharacterRange range) +{ + Sci_TextToFind ttf {range, text.constData(), {-1, -1}}; + int flags = searchFlags(); + + while (send(SCI_FINDTEXT, flags, reinterpret_cast(&ttf)) != -1) { + if(ttf.chrgText.cpMin == ttf.chrgText.cpMax) + break; + ttf.chrg.cpMin = callback(ttf.chrgText.cpMin, ttf.chrgText.cpMax); + } +} + +#endif // SCINTILLANEXT_H diff --git a/src/NotepadNext/SearchResultsCollector.cpp b/src/NotepadNext/SearchResultsCollector.cpp new file mode 100644 index 000000000..a7d257c6a --- /dev/null +++ b/src/NotepadNext/SearchResultsCollector.cpp @@ -0,0 +1,81 @@ +/* + * This file is part of Notepad Next. + * Copyright 2023 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "SearchResultsCollector.h" + +SearchResultsCollector::SearchResultsCollector(ISearchResultsHandler *child) : + child(child) +{ +} + +void SearchResultsCollector::newSearch(const QString searchTerm) +{ + child->newSearch(searchTerm); +} + +void SearchResultsCollector::newFileEntry(ScintillaNext *editor) +{ + // There may be a result that was not passed along yet + if (runningHitCount > 0) { + child->newResultsEntry(prevLine, prevLineNumber, prevStartPositionFromBeginning, prevEndPositionFromBeginning, runningHitCount); + } + runningHitCount = 0; + + child->newFileEntry(editor); +} + +void SearchResultsCollector::newResultsEntry(const QString line, int lineNumber, int startPositionFromBeginning, int endPositionFromBeginning, int hitCount) +{ + if (runningHitCount == 0) { + // Save the previous results since there have not been any yet + prevLine = line; + prevLineNumber = lineNumber; + prevStartPositionFromBeginning = startPositionFromBeginning; + prevEndPositionFromBeginning = endPositionFromBeginning; + + runningHitCount = 1; + } + else if (lineNumber != prevLineNumber) { + // Report the previous data + child->newResultsEntry(prevLine, prevLineNumber, prevStartPositionFromBeginning, prevEndPositionFromBeginning, runningHitCount); + + // Save the new results + prevLine = line; + prevLineNumber = lineNumber; + prevStartPositionFromBeginning = startPositionFromBeginning; + prevEndPositionFromBeginning = endPositionFromBeginning; + + // Just one result now + runningHitCount = 1; + } + else { + runningHitCount += hitCount; + } +} + +void SearchResultsCollector::completeSearch() +{ + // There may be a result that was not passed along yet + if (runningHitCount > 0) { + child->newResultsEntry(prevLine, prevLineNumber, prevStartPositionFromBeginning, prevEndPositionFromBeginning, runningHitCount); + } + runningHitCount = 0; + + child->completeSearch(); +} diff --git a/src/NotepadNext/SearchResultsCollector.h b/src/NotepadNext/SearchResultsCollector.h new file mode 100644 index 000000000..e55395cab --- /dev/null +++ b/src/NotepadNext/SearchResultsCollector.h @@ -0,0 +1,45 @@ +/* + * This file is part of Notepad Next. + * Copyright 2023 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + + +#include "ISearchResultsHandler.h" + +class SearchResultsCollector: public ISearchResultsHandler +{ +public: + SearchResultsCollector(ISearchResultsHandler *child); + virtual ~SearchResultsCollector() {} + + void newSearch(const QString searchTerm) override; + void newFileEntry(ScintillaNext *editor) override; + void newResultsEntry(const QString line, int lineNumber, int startPositionFromBeginning, int endPositionFromBeginning, int hitCount=1) override; + void completeSearch() override; + +private: + ISearchResultsHandler *child; + int runningHitCount = 0; + + QString prevLine; + int prevLineNumber; + int prevStartPositionFromBeginning; + int prevEndPositionFromBeginning; +}; + diff --git a/src/NotepadNext/SelectionTracker.cpp b/src/NotepadNext/SelectionTracker.cpp new file mode 100644 index 000000000..7ffb2e656 --- /dev/null +++ b/src/NotepadNext/SelectionTracker.cpp @@ -0,0 +1,64 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "SelectionTracker.h" +#include "ScintillaNext.h" + +SelectionTracker::SelectionTracker(ScintillaNext *editor) : + editor(editor) +{ + saveSelection(); +} + +SelectionTracker::~SelectionTracker() +{ + restoreSelection(); +} + +void SelectionTracker::saveSelection() +{ + caret = editor->selectionNCaret(editor->mainSelection()); + anchor = editor->selectionNAnchor(editor->mainSelection()); +} + +void SelectionTracker::restoreSelection() +{ + editor->setSelection(caret, anchor); +} + +void SelectionTracker::trackInsertion(int pos, int length) +{ + if (caret >= pos) { + caret += length; + } + if (anchor >=pos) { + anchor += length; + } +} + +void SelectionTracker::trackDeletion(int pos, int length) +{ + // Adjust the caret and anchor. Use the min in case they are within the range being deleted + if (caret > pos) { + caret -= qMin(static_cast(caret - pos), length); + } + if (anchor > pos) { + anchor -= qMin(static_cast(anchor - pos), length); + } +} diff --git a/src/NotepadNext/SelectionTracker.h b/src/NotepadNext/SelectionTracker.h new file mode 100644 index 000000000..87aebb1fd --- /dev/null +++ b/src/NotepadNext/SelectionTracker.h @@ -0,0 +1,43 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SELECTIONTRACKER_H +#define SELECTIONTRACKER_H + +class ScintillaNext; + +class SelectionTracker +{ +public: + explicit SelectionTracker(ScintillaNext *editor); + ~SelectionTracker(); + + void trackInsertion(int pos, int length); + void trackDeletion(int pos, int length); + +private: + void saveSelection(); + void restoreSelection(); + + ScintillaNext *editor; + int caret; + int anchor; +}; + +#endif // SELECTIONTRACKER_H diff --git a/src/NotepadNext/SessionManager.cpp b/src/NotepadNext/SessionManager.cpp new file mode 100644 index 000000000..9249fcb27 --- /dev/null +++ b/src/NotepadNext/SessionManager.cpp @@ -0,0 +1,406 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "BookMarkDecorator.h" +#include "ScintillaNext.h" +#include "MainWindow.h" +#include "SessionManager.h" +#include "EditorManager.h" +#include "NotepadNextApplication.h" + +#include +#include +#include + + +static QString RandomSessionFileName() +{ + return QUuid::createUuid().toString(QUuid::WithoutBraces); +} + +// QList cannot be automatically serialized to/from QSettings (i.e. QVariant) so turn it to a QVariantList +static QVariantList QListToQVariantList(const QList intList) +{ + QVariantList vl; + for (const int i : intList){ + vl.append(i); + } + return vl; +} + +// Do the opposite of the function above +static QList QVariantListToQList(const QVariantList &variantList) { + QList intList; + for (const QVariant &variant : variantList) { + intList.append(variant.toInt()); + } + return intList; +} + +SessionManager::SessionManager(NotepadNextApplication *app, SessionFileTypes types) + : app(app) +{ + setSessionFileTypes(types); +} + +void SessionManager::setSessionFileTypes(SessionFileTypes types) +{ + fileTypes = types; +} + +QDir SessionManager::sessionDirectory() const +{ + QDir d(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + + d.mkpath("session"); + d.cd("session"); + + return d; +} + +void SessionManager::saveIntoSessionDirectory(ScintillaNext *editor, const QString &sessionFileName) const +{ + editor->saveCopyAs(sessionDirectory().filePath(sessionFileName)); +} + +SessionManager::SessionFileType SessionManager::determineType(ScintillaNext *editor) const +{ + if (editor->isFile()) { + if (editor->isSavedToDisk()) { + return SessionManager::SavedFile; + } + else { + return SessionManager::UnsavedFile; + } + } + else { + if (!editor->isSavedToDisk()) { + return SessionManager::TempFile; + } + else { + return SessionManager::None; + } + } +} + +void SessionManager::clear() const +{ + clearSettings(); + clearDirectory(); +} + +void SessionManager::clearSettings() const +{ + ApplicationSettings settings;; + + // Clear everything out. There can be left over entries that are no longer needed + settings.beginGroup("CurrentSession"); + settings.remove(""); +} + +void SessionManager::clearDirectory() const +{ + QDir d = sessionDirectory(); + + for (const QString &f : d.entryList()) { + d.remove(f); + } +} + +void SessionManager::saveSession(MainWindow *window) +{ + qInfo(Q_FUNC_INFO); + + clear(); + + // Early out if no flags are set + if (fileTypes == SessionManager::None) { + return; + } + + const ScintillaNext *currentEditor = window->currentEditor(); + int currentEditorIndex = 0; + ApplicationSettings settings;; + + settings.beginGroup("CurrentSession"); + + settings.beginWriteArray("OpenedFiles"); + + int index = 0; + for (const auto &editor : window->editors()) { + SessionFileType editorType = determineType(editor); + + if (fileTypes.testFlag(editorType)) { + settings.setArrayIndex(index); + + if (editorType == SessionManager::SavedFile) { + storeFileDetails(editor, settings); + } + else if (editorType == SessionManager::UnsavedFile) { + storeUnsavedFileDetails(editor, settings); + } + else if (editorType == SessionManager::TempFile) { + storeTempFile(editor, settings); + } + else { + qWarning("Unknown SessionFileType %d", editorType); + } + + if (currentEditor == editor) { + currentEditorIndex = index; + } + + ++index; + } + } + + settings.endArray(); + + settings.setValue("CurrentEditorIndex", currentEditorIndex); + + settings.endGroup(); +} + +void SessionManager::loadSession(MainWindow *window) +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings settings;; + + settings.beginGroup("CurrentSession"); + + ScintillaNext *currentEditor = Q_NULLPTR; + const int currentEditorIndex = settings.value("CurrentEditorIndex").toInt(); + const int size = settings.beginReadArray("OpenedFiles"); + + // NOTE: In theory the fileTypes should determine what is loaded, however if the session fileTypes + // change from the last time it was saved then it means the settings were manually altered outside of the app, + // which is non-standard behavior, so just load anything in the file + + for (int index = 0; index < size; ++index) { + settings.setArrayIndex(index); + + ScintillaNext *editor = Q_NULLPTR; + + if (settings.contains("Type")) { + const QString type = settings.value("Type").toString(); + + if (type == QStringLiteral("File")) { + editor = loadFileDetails(settings); + } + else if (type == QStringLiteral("UnsavedFile")) { + editor = loadUnsavedFileDetails(settings); + } + else if (type == QStringLiteral("Temp")) { + editor = loadTempFile(settings); + } + else { + qDebug("Unknown session entry type: %s", qUtf8Printable(type)); + } + + if (editor) { + if (currentEditorIndex == index) { + currentEditor = editor; + } + } + } + else { + qDebug("Unknown session entry type for index %d", index); + } + } + + settings.endArray(); + + settings.endGroup(); + + if (currentEditor) { + window->switchToEditor(currentEditor); + } +} + +bool SessionManager::willFileGetStoredInSession(ScintillaNext *editor) const +{ + SessionFileType editorType = determineType(editor); + + // See if the editor type is in the currently supported file types + return fileTypes.testFlag(editorType); +} + +void SessionManager::storeFileDetails(ScintillaNext *editor, QSettings &settings) +{ + settings.setValue("Type", "File"); + settings.setValue("FilePath", editor->getFilePath()); + + storeEditorViewDetails(editor, settings); +} + +ScintillaNext* SessionManager::loadFileDetails(QSettings &settings) +{ + qInfo(Q_FUNC_INFO); + + const QString filePath = settings.value("FilePath").toString(); + + qDebug("Session file: \"%s\"", qUtf8Printable(filePath)); + + ScintillaNext *editor = app->getEditorManager()->getEditorByFilePath(filePath); + if (editor != Q_NULLPTR) { + qDebug(" file is already open, ignoring"); + return Q_NULLPTR; + } + + if (QFileInfo::exists(filePath)) { + editor = ScintillaNext::fromFile(filePath); + + app->getEditorManager()->manageEditor(editor); + + loadEditorViewDetails(editor, settings); + + return editor; + } + else { + qDebug(" no longer exists on disk, ignoring"); + return Q_NULLPTR; + } +} + +void SessionManager::storeUnsavedFileDetails(ScintillaNext *editor, QSettings &settings) +{ + const QString sessionFileName = RandomSessionFileName(); + + settings.setValue("Type", "UnsavedFile"); + settings.setValue("FilePath", editor->getFilePath()); + settings.setValue("SessionFileName", sessionFileName); + + storeEditorViewDetails(editor, settings); + + saveIntoSessionDirectory(editor, sessionFileName); +} + +ScintillaNext *SessionManager::loadUnsavedFileDetails(QSettings &settings) +{ + qInfo(Q_FUNC_INFO); + + const QString filePath = settings.value("FilePath").toString(); + const QString sessionFileName = settings.value("SessionFileName").toString(); + const QString sessionFilePath = sessionDirectory().filePath(sessionFileName); + + qDebug("Session file: \"%s\"", qUtf8Printable(filePath)); + qDebug(" temp loc: \"%s\"", qUtf8Printable(sessionFilePath)); + + ScintillaNext *editor = app->getEditorManager()->getEditorByFilePath(filePath); + if (editor != Q_NULLPTR) { + qDebug(" file is already open, ignoring"); + return Q_NULLPTR; + } + + if (QFileInfo::exists(filePath) && QFileInfo::exists(sessionFilePath)) { + ScintillaNext *editor = ScintillaNext::fromFile(sessionFilePath); + + // Since this editor has different file path info, treat this as a temporary buffer + editor->setFileInfo(filePath); + editor->setTemporary(true); + + loadEditorViewDetails(editor, settings); + + app->getEditorManager()->manageEditor(editor); + + return editor; + } + else { + // What if just filePath exists? + qDebug(" no longer exists on disk, ignoring this file for session loading"); + return Q_NULLPTR; + } +} + +void SessionManager::storeTempFile(ScintillaNext *editor, QSettings &settings) +{ + const QString sessionFileName = RandomSessionFileName(); + + settings.setValue("Type", "Temp"); + settings.setValue("FileName", editor->getName()); + settings.setValue("SessionFileName", sessionFileName); + settings.setValue("Language", editor->languageName); + + storeEditorViewDetails(editor, settings); + + saveIntoSessionDirectory(editor, sessionFileName); +} + +ScintillaNext *SessionManager::loadTempFile(QSettings &settings) +{ + qInfo(Q_FUNC_INFO); + + const QString fileName = settings.value("FileName").toString(); + const QString sessionFileName = settings.value("SessionFileName").toString(); + const QString languageName = settings.value("Language", QString()).toString(); + const QString fullFilePath = sessionDirectory().filePath(sessionFileName); + + qDebug("Session temp file: \"%s\"", qUtf8Printable(fullFilePath)); + + if (QFileInfo::exists(fullFilePath)) { + ScintillaNext *editor = ScintillaNext::fromFile(fullFilePath, false); + + editor->detachFileInfo(fileName); + editor->setTemporary(true); + + app->getEditorManager()->manageEditor(editor); + + loadEditorViewDetails(editor, settings); + + if (!languageName.isEmpty()) { + qDebug("Setting session file language to \"%s\"", qUtf8Printable(languageName)); + app->setEditorLanguage(editor, languageName); + } + + return editor; + } + else { + qDebug(" no longer exists on disk, ignoring"); + return Q_NULLPTR; + } +} + +void SessionManager::storeEditorViewDetails(ScintillaNext *editor, QSettings &settings) +{ + settings.setValue("FirstVisibleLine", static_cast(editor->firstVisibleLine() + 1)); // Keep it 1-based in the settings just for human-readability + settings.setValue("CurrentPosition", static_cast(editor->currentPos())); + + BookMarkDecorator *decorator = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + QList bookMarkedLines = decorator->bookMarkedLines(); + if (bookMarkedLines.length() > 0) + settings.setValue("BookMarks", QListToQVariantList(bookMarkedLines)); +} + +void SessionManager::loadEditorViewDetails(ScintillaNext *editor, QSettings &settings) +{ + const int firstVisibleLine = settings.value("FirstVisibleLine").toInt() - 1; + const int currentPosition = settings.value("CurrentPosition").toInt(); + + editor->setFirstVisibleLine(firstVisibleLine); + editor->setEmptySelection(currentPosition); + + if (settings.contains("BookMarks")) + { + QList bookMarkedLines = QVariantListToQList(settings.value("BookMarks").toList()); // just using .value>() does not work...possibly a Qt bug? + + BookMarkDecorator *decorator = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + decorator->setBookMarkedLines(bookMarkedLines); + } +} diff --git a/src/NotepadNext/SessionManager.h b/src/NotepadNext/SessionManager.h new file mode 100644 index 000000000..86c2efc03 --- /dev/null +++ b/src/NotepadNext/SessionManager.h @@ -0,0 +1,83 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SESSIONMANAGER_H +#define SESSIONMANAGER_H + + +#include +#include + + +class ScintillaNext; +class MainWindow; +class NotepadNextApplication; + +class SessionManager +{ +public: + enum SessionFileType { + None = 0, + SavedFile = 1, + UnsavedFile = 2, + TempFile = 4, + }; + Q_DECLARE_FLAGS(SessionFileTypes, SessionFileType) + + + SessionManager(NotepadNextApplication *app, SessionFileTypes types = SessionFileTypes()); + + void setSessionFileTypes(SessionFileTypes types); + + void clear() const; + + void saveSession(MainWindow *window); + void loadSession(MainWindow *window); + + bool willFileGetStoredInSession(ScintillaNext *editor) const; + +private: + QDir sessionDirectory() const; + + void saveIntoSessionDirectory(ScintillaNext *editor, const QString &sessionFileName) const; + + SessionFileType determineType(ScintillaNext *editor) const; + + void clearSettings() const; + void clearDirectory() const; + + void storeFileDetails(ScintillaNext *editor, QSettings &settings); + ScintillaNext *loadFileDetails(QSettings &settings); + + void storeUnsavedFileDetails(ScintillaNext *editor, QSettings &settings); + ScintillaNext *loadUnsavedFileDetails(QSettings &settings); + + void storeTempFile(ScintillaNext *editor, QSettings &settings); + ScintillaNext *loadTempFile(QSettings &settings); + + void storeEditorViewDetails(ScintillaNext *editor, QSettings &settings); + void loadEditorViewDetails(ScintillaNext *editor, QSettings &settings); + + NotepadNextApplication *app; + SessionFileTypes fileTypes; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(SessionManager::SessionFileTypes) + +#endif // SESSIONMANAGER_H diff --git a/src/NotepadNext/SpinBoxDelegate.cpp b/src/NotepadNext/SpinBoxDelegate.cpp new file mode 100644 index 000000000..74b1f0a0e --- /dev/null +++ b/src/NotepadNext/SpinBoxDelegate.cpp @@ -0,0 +1,61 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "SpinBoxDelegate.h" + +#include + +SpinBoxDelegate::SpinBoxDelegate(QSpinBoxFactory factory, QObject *parent) + : QStyledItemDelegate(parent), factory(factory) +{ +} + +QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option) + Q_UNUSED(index) + + QSpinBox *spinBox = factory(); + spinBox->setParent(parent); + + return spinBox; +} + +void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + int value = index.model()->data(index, Qt::EditRole).toInt(); + + QSpinBox *spinBox = static_cast(editor); + spinBox->setValue(value); +} + +void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + QSpinBox *spinBox = static_cast(editor); + spinBox->interpretText(); + int value = spinBox->value(); + + model->setData(index, value, Qt::EditRole); +} + +void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(index) + + editor->setGeometry(option.rect); +} diff --git a/src/NotepadNext/SpinBoxDelegate.h b/src/NotepadNext/SpinBoxDelegate.h new file mode 100644 index 000000000..e7b3ba784 --- /dev/null +++ b/src/NotepadNext/SpinBoxDelegate.h @@ -0,0 +1,45 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef SPINBOXDELEGATE_H +#define SPINBOXDELEGATE_H + +#include +#include + +typedef QSpinBox*(*QSpinBoxFactory)(); + +class SpinBoxDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + SpinBoxDelegate(QSpinBoxFactory factory, QObject *parent = nullptr); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; + + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +private: + QSpinBoxFactory factory; +}; + +#endif // SPINBOXDELEGATE_H diff --git a/src/NotepadNext/ThemeColors.h b/src/NotepadNext/ThemeColors.h new file mode 100644 index 000000000..e751c8165 --- /dev/null +++ b/src/NotepadNext/ThemeColors.h @@ -0,0 +1,63 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * @author Wayne Zhang + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef THEME_COLORS_H +#define THEME_COLORS_H + +// ########## color utilities ########## + +/** + * Calculate 'negtive' color, that is, compensation color. + * For example, back's compenstation color is white. + */ +#define invertColor(color) ((color) ^ WHITE) + +/** + * Convert RGB color value to BGR, as Lua do the samething, reason unknown. + * To make color RGB values passed from CPP/NotepadNext to Lua scripts the + * same value, convert RGB to BGR: RBB->BGR->BRG = RGB + */ +#define rgb2bgr(x) ((((x) & 0x0000FF) << 16) | ((x) & 0x00FF00) | (((x) & 0xFF0000) >> 16)) + +// ######### color utilities ############# + +#define WHITE 0xFFFFFF +#define BLACK 0x000000 + +#define DARK_DEFAULT_FG WHITE +#define DARK_DEFAULT_BG 0x2D2319 + +#define LIGHT_DEFAULT_FG BLACK +#define LIGHT_DEFAULT_BG WHITE + +// dark theme menu colors +#define DARK_MENU_COLOR 0xE0E1E3 +#define DARK_MENU_BG_COLOR 0x37414F + +#define LIGHT_INTRUCTION_COLOR 0x0000FF // instruction color - blue +#define DARK_INTRUCTION_COLOR 0x00B4F0 // dark mode compensation color + +#define LIGHT_OPERATOR_COLOR 0x800000 // operator color - dark blue +#define DARK_OPERATOR_COLOR WHITE // dark mode compensation color + +#define LIGHT_TYPE_COLOR 0x8000FF // type color +#define DARK_TYPE_COLOR 0xF0B400 // dark mode compenstation color + +#endif diff --git a/src/NotepadNext/TranslationManager.cpp b/src/NotepadNext/TranslationManager.cpp new file mode 100644 index 000000000..99db8542d --- /dev/null +++ b/src/NotepadNext/TranslationManager.cpp @@ -0,0 +1,100 @@ +/* + * This file is part of Notepad Next. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "TranslationManager.h" + +#include +#include +#include + +#include + +QString TranslationFileNameToLocaleName(const QString &baseName) +{ + // return "zh_CN" from "NotepadNext_zh_CN" + return baseName.mid(QApplication::applicationName().length() + 1); // +1 for the underscore +} + + +TranslationManager::TranslationManager(QObject *parent, const QString &path) + : QObject(parent), path(path) +{ +} + +QStringList TranslationManager::availableTranslations() const +{ + QStringList translations; + QDirIterator it(path); + + while (it.hasNext()) { + it.next(); + + if (it.fileName().startsWith(QApplication::applicationName())) { // Some are Qt translation files, not for the application + QString localeName = TranslationFileNameToLocaleName(it.fileInfo().baseName()); + + translations.append(localeName); + } + } + + return translations; +} + +QString TranslationManager::FormatLocaleTerritoryAndLanguage(QLocale &locale) +{ +#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0) + const QString territory = QLocale::countryToString(locale.country()); +#else + const QString territory = QLocale::territoryToString(locale.territory()); +#endif + const QString language = QLocale::languageToString(locale.language()); + return QStringLiteral("%1 / %2").arg(language, territory); +} + +void TranslationManager::loadSystemDefaultTranslation() +{ + // The wrong translation file may be loaded when passing Locale::system() to loadTranslation function, e.g. "zh_CN" translation file will be loaded when the locale is "en_US". It's probably a Qt bug. + loadTranslation(QLocale(QLocale::system().name())); +} + +void TranslationManager::loadTranslation(QLocale locale) +{ + qInfo(Q_FUNC_INFO); + + const QStringList filenames{QStringList{QApplication::applicationName(), "qt", "qtbase"}}; + + for (const auto& filename : filenames) { + std::unique_ptr translator = std::make_unique(); + + if (translator->load(locale, filename, QStringLiteral("_"), path)) { + if (QCoreApplication::installTranslator(translator.get())) { + qInfo() << "Loaded translation" << translator.get()->filePath(); + translators.append(translator.release()); + } + } + } +} + +void TranslationManager::loadTranslationByName(QString localeName) +{ + if (localeName.isEmpty()) { + loadSystemDefaultTranslation(); + } + else { + loadTranslation(QLocale(localeName)); + } +} diff --git a/src/NotepadNext/TranslationManager.h b/src/NotepadNext/TranslationManager.h new file mode 100644 index 000000000..004e69ccf --- /dev/null +++ b/src/NotepadNext/TranslationManager.h @@ -0,0 +1,47 @@ +/* + * This file is part of Notepad Next. + * Copyright 2024 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#pragma once + +#include +#include +#include +#include + + +class TranslationManager : public QObject +{ + Q_OBJECT + +public: + TranslationManager(QObject *parent, const QString &path); + + QStringList availableTranslations() const; + + static QString FormatLocaleTerritoryAndLanguage(QLocale &locale); + +public slots: + void loadSystemDefaultTranslation(); + void loadTranslation(QLocale locale); + void loadTranslationByName(QString localeName); + +private: + const QString path; + + QList translators; +}; diff --git a/src/NotepadNext/UndoAction.cpp b/src/NotepadNext/UndoAction.cpp new file mode 100644 index 000000000..8e1e816f6 --- /dev/null +++ b/src/NotepadNext/UndoAction.cpp @@ -0,0 +1,33 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "UndoAction.h" +#include "ScintillaNext.h" + +UndoAction::UndoAction(ScintillaNext *editor) : + editor(editor) +{ + editor->beginUndoAction(); +} + +UndoAction::~UndoAction() +{ + editor->endUndoAction(); +} + diff --git a/src/NotepadNext/UndoAction.h b/src/NotepadNext/UndoAction.h new file mode 100644 index 000000000..52983fdf3 --- /dev/null +++ b/src/NotepadNext/UndoAction.h @@ -0,0 +1,35 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef UNDOACTION_H +#define UNDOACTION_H + +class ScintillaNext; + +class UndoAction +{ +public: + explicit UndoAction(ScintillaNext *editor); + ~UndoAction(); + +private: + ScintillaNext *editor; +}; + +#endif // UNDOACTION_H diff --git a/src/NotepadNext/ZoomEventWatcher.cpp b/src/NotepadNext/ZoomEventWatcher.cpp new file mode 100644 index 000000000..d03b1106d --- /dev/null +++ b/src/NotepadNext/ZoomEventWatcher.cpp @@ -0,0 +1,67 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "ZoomEventWatcher.h" + +#include +#include +#include + + +static bool isWheelEventHorizontal(QWheelEvent *event) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + return event->angleDelta().y() == 0; +#else + return event->orientation() == Qt::Horizontal; +#endif +} + +static int wheelEventYDelta(QWheelEvent *event) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + return event->angleDelta().y(); +#else + return event->delta(); +#endif +} + + +ZoomEventWatcher::ZoomEventWatcher(QObject *parent) + : QObject{parent} +{ +} + +bool ZoomEventWatcher::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::Wheel) { + QWheelEvent *wheelEvent = static_cast(event); + + if (!isWheelEventHorizontal(wheelEvent)) { + if (QApplication::keyboardModifiers() & Qt::ControlModifier) { + if (wheelEventYDelta(wheelEvent) > 0) { + emit zoomIn(); + } else { + emit zoomOut(); + } + return true; + } + } + } + + return QObject::eventFilter(obj, event); +} diff --git a/src/NotepadNext/ZoomEventWatcher.h b/src/NotepadNext/ZoomEventWatcher.h new file mode 100644 index 000000000..d59412115 --- /dev/null +++ b/src/NotepadNext/ZoomEventWatcher.h @@ -0,0 +1,40 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef ZOOMEVENTWATCHER_H +#define ZOOMEVENTWATCHER_H + +#include + +class ZoomEventWatcher : public QObject +{ + Q_OBJECT + +public: + explicit ZoomEventWatcher(QObject *parent = nullptr); + +signals: + void zoomIn(); + void zoomOut(); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; +}; + +#endif // ZOOMEVENTWATCHER_H diff --git a/src/NotepadNext/decorators/ApplicationDecorator.cpp b/src/NotepadNext/decorators/ApplicationDecorator.cpp new file mode 100644 index 000000000..f36c9bbe3 --- /dev/null +++ b/src/NotepadNext/decorators/ApplicationDecorator.cpp @@ -0,0 +1,26 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "ApplicationDecorator.h" + +void ApplicationDecorator::setEnabled(bool b) +{ + enabled = b; + + emit stateChanged(enabled); +} diff --git a/src/NotepadNext/decorators/ApplicationDecorator.h b/src/NotepadNext/decorators/ApplicationDecorator.h new file mode 100644 index 000000000..53016baf0 --- /dev/null +++ b/src/NotepadNext/decorators/ApplicationDecorator.h @@ -0,0 +1,48 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef APPLICATIONDECORATOR_H +#define APPLICATIONDECORATOR_H + +#include + +#include "NotepadNextApplication.h" + +class ApplicationDecorator : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY stateChanged) + +public: + explicit ApplicationDecorator(NotepadNextApplication *app) : QObject(app), app(app) {} + + bool isEnabled() const { return enabled; } + +public slots: + void setEnabled(bool b); + +signals: + void stateChanged(bool b); + +protected: + NotepadNextApplication *app; + bool enabled = false; + +}; + +#endif // APPLICATIONDECORATOR_H diff --git a/src/NotepadNext/decorators/AutoCompletion.cpp b/src/NotepadNext/decorators/AutoCompletion.cpp new file mode 100644 index 000000000..1dbfe067a --- /dev/null +++ b/src/NotepadNext/decorators/AutoCompletion.cpp @@ -0,0 +1,77 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "AutoCompletion.h" + +#include + + +using namespace Scintilla; + +AutoCompletion::AutoCompletion(ScintillaNext *editor) : + EditorDecorator(editor) +{ + editor->autoCSetOrder(SC_ORDER_PERFORMSORT); + editor->autoCSetMaxHeight(10); +} + +void AutoCompletion::notify(const NotificationData *pscn) +{ + if (pscn->nmhdr.code == Notification::CharAdded) { + if (editor->autoCActive()) + return; + + showAutoCompletion(); + } +} + +void AutoCompletion::showAutoCompletion() +{ + int curPos = editor->currentPos(); + int startPos = editor->wordStartPosition(curPos, true); + int endPos = editor->wordEndPosition(curPos, true); + + // Need a minimum number of characters to trigger auto completion + if ((curPos - startPos) < 3) + return; + + const QByteArray current_word = editor->get_text_range(startPos, curPos); + const QByteArray regex = "\\b" + current_word + "[\\w]*"; + QSet words; + + editor->setSearchFlags(SCFIND_REGEXP | SCFIND_MATCHCASE); + + // Don't want to find the word that's currently being typed + + // Find everything before this word + editor->forEachMatchInRange(regex, [&](int start, int end) { + words.insert(editor->get_text_range(start, end)); + return end; + }, { 0, startPos}); + + // Find everything after this word + editor->forEachMatchInRange(regex, [&](int start, int end) { + words.insert(editor->get_text_range(start, end)); + return end; + }, { endPos, (Sci_PositionCR)editor->length()}); + + if (!words.isEmpty()) { + editor->autoCShow(current_word.length(), words.values().join(' ')); + } +} diff --git a/src/NotepadNext/decorators/AutoCompletion.h b/src/NotepadNext/decorators/AutoCompletion.h new file mode 100644 index 000000000..b35e77923 --- /dev/null +++ b/src/NotepadNext/decorators/AutoCompletion.h @@ -0,0 +1,38 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef AUTOCOMPLETION_H +#define AUTOCOMPLETION_H + +#include "EditorDecorator.h" + + +class AutoCompletion : public EditorDecorator +{ + Q_OBJECT + +public: + explicit AutoCompletion(ScintillaNext *editor); + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; + void showAutoCompletion(); +}; + +#endif // AUTOCOMPLETION_H diff --git a/src/NotepadNext/decorators/AutoIndentation.cpp b/src/NotepadNext/decorators/AutoIndentation.cpp new file mode 100644 index 000000000..4387355d6 --- /dev/null +++ b/src/NotepadNext/decorators/AutoIndentation.cpp @@ -0,0 +1,51 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "AutoIndentation.h" + + +using namespace Scintilla; + +AutoIndentation::AutoIndentation(ScintillaNext *editor) : + EditorDecorator(editor) +{ +} + +void AutoIndentation::notify(const NotificationData *pscn) +{ + if (pscn->nmhdr.code == Notification::CharAdded) { + const int ch = pscn->ch; + const int eolMode = editor->eOLMode(); + + if (((eolMode == SC_EOL_CRLF || eolMode == SC_EOL_LF) && ch == '\n') || (eolMode == SC_EOL_CR && ch == '\r')) { + autoIndentLine(editor->lineFromPosition(editor->currentPos())); + } + } +} + +void AutoIndentation::autoIndentLine(int line) const +{ + const int previousLine = line - 1; + const int previousIndentation = editor->lineIndentation(previousLine); + + if (previousIndentation > 0) { + editor->setLineIndentation(line, previousIndentation); + editor->gotoPos(editor->findColumn(line, previousIndentation)); + } +} diff --git a/src/NotepadNext/decorators/AutoIndentation.h b/src/NotepadNext/decorators/AutoIndentation.h new file mode 100644 index 000000000..508f7a9e0 --- /dev/null +++ b/src/NotepadNext/decorators/AutoIndentation.h @@ -0,0 +1,40 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef AUTOINDENTATION_H +#define AUTOINDENTATION_H + +#include "EditorDecorator.h" + + +class AutoIndentation : public EditorDecorator +{ + Q_OBJECT + +public: + AutoIndentation(ScintillaNext *editor); + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; + +private: + void autoIndentLine(int line) const; +}; + +#endif // AUTOINDENTATION_H diff --git a/src/NotepadNext/decorators/BetterMultiSelection.cpp b/src/NotepadNext/decorators/BetterMultiSelection.cpp new file mode 100644 index 000000000..d4d62624c --- /dev/null +++ b/src/NotepadNext/decorators/BetterMultiSelection.cpp @@ -0,0 +1,239 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include +#include + +#include "BetterMultiSelection.h" + + + +struct Selection { + int caret; + int anchor; + + Selection(int caret, int anchor) : caret(caret), anchor(anchor) {} + + int start() const { return qMin(caret, anchor); } + int end() const { return qMax(caret, anchor); } + int length() const { return end() - start(); } + void set(int pos) { anchor = caret = pos; } + void offset(int offset) { anchor += offset; caret += offset; } +}; + +template +It uniquify(It begin, It const end) +{ + std::vector v; + v.reserve(static_cast(std::distance(begin, end))); + + for (It i = begin; i != end; ++i) + v.push_back(i); + + std::sort(v.begin(), v.end(), [](const auto &lhs, const auto &rhs) { + return (*lhs).start() < (*rhs).start() || (!((*rhs).start() < (*lhs).start()) && (*lhs).end() < (*rhs).end()); + }); + + v.erase(std::unique(v.begin(), v.end(), [](const auto &lhs, const auto &rhs) { + return (*lhs).start() == (*rhs).start() && (*lhs).end() == (*rhs).end(); + }), v.end()); + + std::sort(v.begin(), v.end()); + + size_t j = 0; + for (It i = begin; i != end && j != v.size(); ++i) { + if (i == v[j]) { + using std::iter_swap; iter_swap(i, begin); + ++j; + ++begin; + } + } + return begin; +} + +BetterMultiSelection::BetterMultiSelection(ScintillaNext *editor) : + EditorDecorator(editor) +{ + setObjectName("BetterMultiSelection"); + + // Allow insertion of autocompletion at each cursor + editor->autoCSetMulti(SC_MULTIAUTOC_EACH); + + editor->installEventFilter(this); +} + +bool BetterMultiSelection::eventFilter(QObject *obj, QEvent *event) +{ + Q_UNUSED(obj) + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + bool isAltPresssed = (keyEvent->modifiers() & Qt::AltModifier); + bool isControlPresssed = (keyEvent->modifiers() & Qt::ControlModifier); + bool isShiftPressed = (keyEvent->modifiers() & Qt::ShiftModifier); + + if (isAltPresssed) + return false; + + if (editor->selections() > 1) { + if (isControlPresssed) { + if (keyEvent->key() == Qt::Key_Left) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_WORDLEFTEXTEND : SCI_WORDLEFT)); + return true; + } + else if (keyEvent->key() == Qt::Key_Right) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_WORDRIGHTENDEXTEND : SCI_WORDRIGHT)); + return true; + } + else if (keyEvent->key() == Qt::Key_Back) { + EditSelections(SimpleEdit(SCI_DELWORDLEFT)); + return true; + } + else if (keyEvent->key() == Qt::Key_Delete) { + EditSelections(SimpleEdit(SCI_DELWORDRIGHT)); + return true; + } + //else if (keyEvent->key() == Qt::Key_X || keyEvent->key() == Qt::Key_C) { + // if (CopyToClipboard(editor)) { + // if (keyEvent->key() == Qt::Key_X) { + // EditSelections(SimpleEdit(SCI_DELETEBACK)); + // } + // return true; + // } + //} + //else if (keyEvent->key() == Qt::Key_V) { + // if (Paste(editor)) { + // return true; + // } + //} + } + else { + if (keyEvent->key() == Qt::Key_Escape) { + int caret = editor->selectionNCaret(editor->mainSelection()); + editor->setSelection(caret, caret); + return true; + } + else if (keyEvent->key() == Qt::Key_Left) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_CHARLEFTEXTEND : SCI_CHARLEFT)); + return true; + } + else if (keyEvent->key() == Qt::Key_Right) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_CHARRIGHTEXTEND : SCI_CHARRIGHT)); + return true; + } + else if (keyEvent->key() == Qt::Key_Home) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_VCHOMEWRAPEXTEND : SCI_VCHOMEWRAP)); + return true; + } + else if (keyEvent->key() == Qt::Key_End) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_LINEENDWRAPEXTEND : SCI_LINEENDWRAP)); + return true; + } + else if (keyEvent->key() == Qt::Key_Return) { + if (!editor->autoCActive()) { + EditSelections(SimpleEdit(SCI_NEWLINE)); + return true; + } + // else just let Scintilla handle the insertion of autocompletion + } + else if (keyEvent->key() == Qt::Key_Up) { + if (!editor->autoCActive()) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_LINEUPEXTEND : SCI_LINEUP)); + return true; + } + // else just let Scintilla handle the navigation of autocompletion + } + else if (keyEvent->key() == Qt::Key_Down) { + if (!editor->autoCActive()) { + EditSelections(SimpleEdit(isShiftPressed ? SCI_LINEDOWNEXTEND : SCI_LINEDOWN)); + return true; + } + // else just let Scintilla handle the navigation of autocompletion + } + } + } + } + + return false; +} + +void BetterMultiSelection::notify(const Scintilla::NotificationData *pscn) +{ + Q_UNUSED(pscn); +} + +QVector BetterMultiSelection::GetSelections() { + QVector selections; + + int num = editor->selections(); + for (int i = 0; i < num; ++i) { + int caret = editor->selectionNCaret(i); + int anchor = editor->selectionNAnchor(i); + selections.append(Selection{ caret, anchor }); + } + + return selections; +} + +void BetterMultiSelection::SetSelections(const QVector &selections) { + for (auto i = 0; i < selections.size(); ++i) { + if (i == 0) + editor->setSelection(selections[i].caret, selections[i].anchor); + else + editor->addSelection(selections[i].caret, selections[i].anchor); + } +} + +void BetterMultiSelection::EditSelections(std::function edit) { + auto selections = GetSelections(); + + editor->clearSelections(); + + std::sort(selections.begin(), selections.end(), [](const auto &lhs, const auto &rhs) { + return lhs.start() < rhs.start() || (!(rhs.start() < lhs.start()) && lhs.end() < rhs.end()); + }); + + editor->beginUndoAction(); + + int totalOffset = 0; + for (auto &selection : selections) { + selection.offset(totalOffset); + const int length = editor->length(); + + edit(selection); + + totalOffset += editor->length() - length; + } + + editor->endUndoAction(); + + selections.erase(uniquify(selections.begin(), selections.end()), selections.end()); + + SetSelections(selections); +} + +std::function BetterMultiSelection::SimpleEdit(int message) { + return [=](Selection &selection) { + editor->setSelection(selection.caret, selection.anchor); + editor->send(message); + + selection.caret = editor->selectionNCaret(0); + selection.anchor = editor->selectionNAnchor(0); + }; +} diff --git a/src/NotepadNext/decorators/BetterMultiSelection.h b/src/NotepadNext/decorators/BetterMultiSelection.h new file mode 100644 index 000000000..b9ac148b9 --- /dev/null +++ b/src/NotepadNext/decorators/BetterMultiSelection.h @@ -0,0 +1,52 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef BETTERMULTISELECTION_H +#define BETTERMULTISELECTION_H + + +#include +#include + +#include "EditorDecorator.h" + + +struct Selection; + +class BetterMultiSelection : public EditorDecorator +{ + Q_OBJECT + +public: + BetterMultiSelection(ScintillaNext *editor); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; + +private: + QVector GetSelections(); + void SetSelections(const QVector &selections); + void EditSelections(std::function edit); + std::function SimpleEdit(int message); +}; + +#endif // BETTERMULTISELECTION_H diff --git a/src/NotepadNext/decorators/BookMarkDecorator.cpp b/src/NotepadNext/decorators/BookMarkDecorator.cpp new file mode 100644 index 000000000..9f51336c4 --- /dev/null +++ b/src/NotepadNext/decorators/BookMarkDecorator.cpp @@ -0,0 +1,116 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "BookMarkDecorator.h" + +const int MARK_BOOKMARK = 24; +const int MARGIN = 1; + +BookMarkDecorator::BookMarkDecorator(ScintillaNext *editor) : + EditorDecorator(editor) +{ + editor->markerSetAlpha(MARK_BOOKMARK, 70); + editor->markerDefine(MARK_BOOKMARK, SC_MARK_BOOKMARK); + editor->markerSetFore(MARK_BOOKMARK, 0xFF2020); + editor->markerSetBack(MARK_BOOKMARK, 0xFF2020); + + int mask = editor->marginMaskN(MARGIN); + editor->setMarginMaskN(MARGIN, (1 << MARK_BOOKMARK) | mask); + + editor->setMarginSensitiveN(MARGIN, true); +} + +void BookMarkDecorator::toggleBookmark(int line) +{ + if (editor->markerGet(line) & (1 << MARK_BOOKMARK)) { + // The marker can be set multiple times, so keep deleting it till it is no longer set + while (editor->markerGet(line) & (1 << MARK_BOOKMARK)) { + editor->markerDelete(line, MARK_BOOKMARK); + } + } + else { + editor->markerAdd(line, MARK_BOOKMARK); + } +} + +int BookMarkDecorator::nextBookmarkAfter(int line) +{ + int nextMarkedLine = editor->markerNext(line, 1 << MARK_BOOKMARK); + + if (nextMarkedLine == -1) { + return editor->markerNext(0, 1 << MARK_BOOKMARK); + } + else { + return nextMarkedLine; + } +} + +int BookMarkDecorator::previousBookMarkBefore(int line) +{ + int prevMarkedLine = editor->markerPrevious(line, 1 << MARK_BOOKMARK); + + if (prevMarkedLine == -1) { + return editor->markerPrevious(editor->lineCount(), 1 << MARK_BOOKMARK); + } + else { + return prevMarkedLine; + } +} + +void BookMarkDecorator::clearBookmarks() +{ + editor->markerDeleteAll(MARK_BOOKMARK); +} + +QList BookMarkDecorator::bookMarkedLines() const +{ + QList bookMarkedLines; + + int line = 0; + forever { + line = editor->markerNext(line, 1 << MARK_BOOKMARK); + + if (line != -1) { + bookMarkedLines.append(line); + line++; + } + else { + break; + } + } + + return bookMarkedLines; +} + +void BookMarkDecorator::setBookMarkedLines(QList &lines) +{ + for(const int i : lines) { + editor->markerAdd(i, MARK_BOOKMARK); + } +} + +void BookMarkDecorator::notify(const Scintilla::NotificationData *pscn) +{ + if (pscn->nmhdr.code == Scintilla::Notification::MarginClick) { + if (pscn->margin == MARGIN) { + int line = editor->lineFromPosition(pscn->position); + toggleBookmark(line); + } + } +} diff --git a/src/NotepadNext/decorators/BookMarkDecorator.h b/src/NotepadNext/decorators/BookMarkDecorator.h new file mode 100644 index 000000000..e442d5940 --- /dev/null +++ b/src/NotepadNext/decorators/BookMarkDecorator.h @@ -0,0 +1,41 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#pragma once + +#include "EditorDecorator.h" + + +class BookMarkDecorator : public EditorDecorator +{ + Q_OBJECT + +public: + BookMarkDecorator(ScintillaNext *editor); + + void toggleBookmark(int line); + int nextBookmarkAfter(int line); + int previousBookMarkBefore(int line); + void clearBookmarks(); + QList bookMarkedLines() const; + void setBookMarkedLines(QList &lines); + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; +}; diff --git a/src/NotepadNext/decorators/BraceMatch.cpp b/src/NotepadNext/decorators/BraceMatch.cpp new file mode 100644 index 000000000..981d3422e --- /dev/null +++ b/src/NotepadNext/decorators/BraceMatch.cpp @@ -0,0 +1,112 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "Sci_Position.h" + +#include "BraceMatch.h" + +using namespace Scintilla; + + +BraceMatch::BraceMatch(ScintillaNext *editor) : + EditorDecorator(editor) +{ + setObjectName("BraceMatch"); + + const int braceHighlight = editor->allocateIndicator("brace_highlight"); + const int braceBadlight = editor->allocateIndicator("brace_badlight"); + + editor->indicSetStyle(braceHighlight, INDIC_FULLBOX); + editor->indicSetFore(braceHighlight, 0x999999); + editor->indicSetAlpha(braceHighlight, 100); + editor->indicSetOutlineAlpha(braceHighlight, 200); + editor->indicSetUnder(braceHighlight, true); + editor->braceHighlightIndicator(true, braceHighlight); + + editor->indicSetStyle(braceBadlight, INDIC_FULLBOX); + editor->indicSetFore(braceBadlight, 0x0000FF); + editor->indicSetAlpha(braceBadlight, 100); + editor->indicSetOutlineAlpha(braceBadlight, 200); + editor->indicSetUnder(braceBadlight, true); + editor->braceBadLightIndicator(true, braceBadlight); + + connect(this, &EditorDecorator::stateChanged, [=](bool b) { + if (b) { + doHighlighting(); + } + else { + clearHighlighting(); + } + }); +} + +void BraceMatch::doHighlighting() +{ + static const QList braces = {'[', ']', '(', ')', '{', '}'}; + + const Sci_Position pos = static_cast(editor->currentPos()); + + // Check the character before the caret first + int match = editor->braceMatch(pos - 1, 0); + + if (match != INVALID_POSITION) { + editor->braceHighlight(pos - 1, match); + editor->setHighlightGuide(editor->column(editor->lineIndentPosition(editor->lineFromPosition(pos - 1)))); + } + else { + // Check the character after the caret + match = editor->braceMatch(pos, 0); + if (match != INVALID_POSITION) { + editor->braceHighlight(pos, match); + editor->setHighlightGuide(editor->column(editor->lineIndentPosition(editor->lineFromPosition(pos)))); + } + else { + // Nothing was found, now check to see if we need to badlight something + // by checking the characters + char c = static_cast(editor->charAt(pos - 1)); + if (braces.contains(c)) { + editor->braceBadLight(pos - 1); + } + else { + c = static_cast(editor->charAt(pos)); + if (braces.contains(c)) { + editor->braceBadLight(pos); + } + else { + clearHighlighting(); + } + } + } + } +} + +void BraceMatch::clearHighlighting() +{ + editor->braceHighlight(INVALID_POSITION, INVALID_POSITION); + editor->setHighlightGuide(0); +} + +void BraceMatch::notify(const NotificationData *pscn) +{ + if (pscn->nmhdr.code == Notification::UpdateUI) { + if (FlagSet(pscn->updated, Update::Content) || FlagSet(pscn->updated, Update::Selection)) { + doHighlighting(); + } + } +} diff --git a/src/NotepadNext/decorators/BraceMatch.h b/src/NotepadNext/decorators/BraceMatch.h new file mode 100644 index 000000000..546403a83 --- /dev/null +++ b/src/NotepadNext/decorators/BraceMatch.h @@ -0,0 +1,41 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef BRACEMATCH_H +#define BRACEMATCH_H + +#include "EditorDecorator.h" + + +class BraceMatch : public EditorDecorator +{ + Q_OBJECT + +public: + BraceMatch(ScintillaNext *editor); + +private: + void doHighlighting(); + void clearHighlighting(); + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; +}; + +#endif // BRACEMATCH_H diff --git a/src/NotepadNext/decorators/EditorConfigAppDecorator.cpp b/src/NotepadNext/decorators/EditorConfigAppDecorator.cpp new file mode 100644 index 000000000..de353cc47 --- /dev/null +++ b/src/NotepadNext/decorators/EditorConfigAppDecorator.cpp @@ -0,0 +1,147 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "EditorConfigAppDecorator.h" +#include "EditorManager.h" +#include "ScintillaNext.h" +#include "Finder.h" + +#include "EditorConfig.h" + +class PreventUnfolding +{ +public: + explicit PreventUnfolding(ScintillaNext *editor) : editor(editor) { + foldFlags = editor->automaticFold(); + editor->setAutomaticFold(0); + } + + ~PreventUnfolding() { + editor->setAutomaticFold(foldFlags); + } + +private: + ScintillaNext *editor; + int foldFlags; +}; + + +EditorConfigAppDecorator::EditorConfigAppDecorator(NotepadNextApplication *app) + : ApplicationDecorator(app) +{ + EditorManager *manager = app->getEditorManager(); + + connect(manager, &EditorManager::editorCreated, this, &EditorConfigAppDecorator::doEditorConfig); + // TODO: on editor reload +} + +void EditorConfigAppDecorator::doEditorConfig(ScintillaNext *editor) +{ + if (this->isEnabled()) { + if (editor->isFile()) { + EditorConfigSettings settings = EditorConfig::getFileSettings(editor->getFilePath()); + + qDebug() << "EditorConfig settings for:" << editor->getFilePath(); + for(auto &setting : settings.toStdMap()) { + qDebug() << setting.first << "=" << setting.second; + } + + if (settings.contains(QStringLiteral("indent_style"))) { + if (settings[QStringLiteral("indent_style")] == QStringLiteral("tab")) editor->setUseTabs(true); + else if (settings[QStringLiteral("indent_style")] == QStringLiteral("space")) editor->setUseTabs(false); + + // Set a flag so that the tab/spaces won't get overridden + editor->QObject::setProperty("nn_skip_usetabs", "EditorConfig"); + } + + if (settings.contains(QStringLiteral("indent_size")) && settings[QStringLiteral("indent_size")].toInt() > 0) { + editor->setIndent(settings[QStringLiteral("indent_size")].toInt()); + } + + if (settings.contains(QStringLiteral("tab_width")) && settings[QStringLiteral("tab_width")].toInt() > 0) { + editor->setTabWidth(settings[QStringLiteral("tab_width")].toInt()); + + // Set a flag so that the tab width won't get overridden + editor->QObject::setProperty("nn_skip_tabwidth", "EditorConfig"); + } + + if (settings.contains(QStringLiteral("end_of_line"))) { + if (settings[QStringLiteral("end_of_line")] == QStringLiteral("lf")) editor->setEOLMode(SC_EOL_LF); + else if (settings[QStringLiteral("end_of_line")] == QStringLiteral("cr")) editor->setEOLMode(SC_EOL_CR); + else if (settings[QStringLiteral("end_of_line")] == QStringLiteral("crlf")) editor->setEOLMode(SC_EOL_CRLF); + } + + if (settings.contains(QStringLiteral("trim_trailing_whitespace"))) { + if (settings[QStringLiteral("trim_trailing_whitespace")] == QStringLiteral("true")) { + connect(editor, &ScintillaNext::aboutToSave, this, &EditorConfigAppDecorator::trimTrailingWhitespace); + } + } + + if (settings.contains(QStringLiteral("insert_final_newline"))) { + if (settings[QStringLiteral("insert_final_newline")] == QStringLiteral("true")) { + connect(editor, &ScintillaNext::aboutToSave, this, &EditorConfigAppDecorator::ensureFinalNewline); + } + else if (settings[QStringLiteral("insert_final_newline")] == QStringLiteral("false")) { + connect(editor, &ScintillaNext::aboutToSave, this, &EditorConfigAppDecorator::ensureNoFinalNewline); + } + } + } + } +} + +void EditorConfigAppDecorator::trimTrailingWhitespace() +{ + ScintillaNext *editor = qobject_cast(sender()); + Finder f(editor); + const PreventUnfolding pu(editor); + + // NOTE: see note in QRegexSearch about (*ANYCRLF) + f.setSearchText("(*ANYCRLF)[ \t]+$"); + f.setSearchFlags(SCFIND_REGEXP); + f.replaceAll(""); +} + +void EditorConfigAppDecorator::ensureFinalNewline() +{ + ScintillaNext *editor = qobject_cast(sender()); + const PreventUnfolding pu(editor); + const int lastLine = editor->lineCount() - 1; + const int lastLineLength = editor->lineEndPosition(lastLine) - editor->positionFromLine(lastLine); + + if (lastLineLength != 0) { + switch (editor->eOLMode()) { + case SC_EOL_CRLF: + editor->appendText(2, "\r\n"); + break; + case SC_EOL_CR: + editor->appendText(1, "\r"); + break; + case SC_EOL_LF: + editor->appendText(1, "\n"); + break; + } + } +} + +void EditorConfigAppDecorator::ensureNoFinalNewline() +{ + ScintillaNext *editor = qobject_cast(sender()); + const PreventUnfolding pu(editor); + + editor->deleteTrailingEmptyLines(); +} diff --git a/src/NotepadNext/decorators/EditorConfigAppDecorator.h b/src/NotepadNext/decorators/EditorConfigAppDecorator.h new file mode 100644 index 000000000..92c28cd2e --- /dev/null +++ b/src/NotepadNext/decorators/EditorConfigAppDecorator.h @@ -0,0 +1,41 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef EDITORCONFIGAPPDECORATOR_H +#define EDITORCONFIGAPPDECORATOR_H + +#include "ApplicationDecorator.h" + +class ScintillaNext; + +class EditorConfigAppDecorator : public ApplicationDecorator +{ + Q_OBJECT + +public: + explicit EditorConfigAppDecorator(NotepadNextApplication *app); + +private slots: + void doEditorConfig(ScintillaNext *editor); + + void trimTrailingWhitespace(); + void ensureFinalNewline(); + void ensureNoFinalNewline(); +}; + +#endif // EDITORCONFIGAPPDECORATOR_H diff --git a/src/NotepadNext/decorators/EditorDecorator.cpp b/src/NotepadNext/decorators/EditorDecorator.cpp new file mode 100644 index 000000000..9ffbfd18e --- /dev/null +++ b/src/NotepadNext/decorators/EditorDecorator.cpp @@ -0,0 +1,34 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "EditorDecorator.h" + +void EditorDecorator::setEnabled(bool b) +{ + enabled = b; + + if (enabled) { + connect(editor, &ScintillaEdit::notify, this, &EditorDecorator::notify); + } + else { + disconnect(editor, nullptr, this, nullptr); + } + + emit stateChanged(enabled); +} diff --git a/src/NotepadNext/decorators/EditorDecorator.h b/src/NotepadNext/decorators/EditorDecorator.h new file mode 100644 index 000000000..3b230fa72 --- /dev/null +++ b/src/NotepadNext/decorators/EditorDecorator.h @@ -0,0 +1,51 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef EDITORDECORATOR_H +#define EDITORDECORATOR_H + +#include + +#include "ScintillaNext.h" + +class EditorDecorator : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY stateChanged) + +public: + explicit EditorDecorator(ScintillaNext *editor) : QObject(editor), editor(editor) {} + virtual ~EditorDecorator() {} + + bool isEnabled() const { return enabled; } + ScintillaNext *getEditor() const { return editor; } + +public slots: + void setEnabled(bool b); + virtual void notify(const Scintilla::NotificationData *pscn) = 0; + +signals: + void stateChanged(bool b); + +protected: + ScintillaNext *editor; + bool enabled = false; +}; + +#endif // EDITORDECORATOR_H diff --git a/src/NotepadNext/decorators/HighlightedScrollBar.cpp b/src/NotepadNext/decorators/HighlightedScrollBar.cpp new file mode 100644 index 000000000..779196859 --- /dev/null +++ b/src/NotepadNext/decorators/HighlightedScrollBar.cpp @@ -0,0 +1,143 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include + +#include "HighlightedScrollBar.h" + + +using namespace Scintilla; + +const int DEFAULT_TICK_HEIGHT = 3; +const int DEFAULT_TICK_PADDING = 3; +const QColor CURSOR_SELECTION_COLOR = QColor(0, 0, 0, 25); +const QColor CURSOR_CARET_COLOR = QColor(0, 0, 0, 100); + +HighlightedScrollBarDecorator::HighlightedScrollBarDecorator(ScintillaNext *editor) + : EditorDecorator(editor), scrollBar(new HighlightedScrollBar(editor, Qt::Vertical, editor)) +{ + connect(scrollBar, &QScrollBar::valueChanged, editor, &ScintillaEdit::scrollVertical); + + editor->setVerticalScrollBar(scrollBar); +} + +HighlightedScrollBarDecorator::~HighlightedScrollBarDecorator() +{ +} + +void HighlightedScrollBarDecorator::notify(const NotificationData *pscn) +{ + if (pscn->nmhdr.code == Notification::UpdateUI && (FlagSet(pscn->updated, Update::Content) || FlagSet(pscn->updated, Update::Selection))) { + scrollBar->update(); + } + else if (pscn->nmhdr.code == Notification::Modified && FlagSet(pscn->modificationType, ModificationFlags::ChangeMarker)) { + scrollBar->update(); + } +} + + + + +HighlightedScrollBar::HighlightedScrollBar(ScintillaNext *editor, Qt::Orientation orientation, QWidget *parent) + : QScrollBar(orientation, parent), editor(editor) +{ + smartHighlighterIndicator = editor->allocateIndicator("smart_highlighter"); +} + +void HighlightedScrollBar::paintEvent(QPaintEvent *event) +{ + // Paint the default scrollbar first + QScrollBar::paintEvent(event); + QPainter p(this); + + drawMarker(p, 24); + drawIndicator(p, smartHighlighterIndicator); + drawCursors(p); +} + +void HighlightedScrollBar::drawMarker(QPainter &p, int marker) +{ + // NOTE: SCI_MARKERGETBACK doesn't exist...so can't use the marker color + int curLine = 0; + + while ((curLine = editor->markerNext(curLine, 1 << marker)) != -1) { + drawTickMark(p, lineToScrollBarY(curLine), DEFAULT_TICK_HEIGHT, QColor(100, 100, 255)); + + curLine++; + } +} + +void HighlightedScrollBar::drawIndicator(QPainter &p, int indicator) +{ + int curPos = editor->indicatorEnd(indicator, 0); + int color = editor->indicFore(indicator); + + if (curPos > 0) { + while ((curPos = editor->indicatorEnd(indicator, curPos)) < editor->length()) { + drawTickMark(p, posToScrollBarY(curPos), DEFAULT_TICK_HEIGHT, color); + + curPos = editor->indicatorEnd(indicator, curPos); + } + } +} + +void HighlightedScrollBar::drawCursors(QPainter &p) +{ + for (int i = 0; i < editor->selections() ; i++) { + int startCaretY = posToScrollBarY(editor->selectionNCaret(i)); + int startAnchorY = posToScrollBarY(editor->selectionNAnchor(i)); + + if (startCaretY != startAnchorY) { + drawTickMark(p, startAnchorY, startCaretY - startAnchorY, CURSOR_SELECTION_COLOR); + } + + drawTickMark(p, startCaretY, DEFAULT_TICK_HEIGHT, CURSOR_CARET_COLOR); + } +} + +void HighlightedScrollBar::drawTickMark(QPainter &p, int y, int height, QColor color) +{ + p.fillRect(rect().x() + DEFAULT_TICK_PADDING, y + scrollbarArrowHeight(), rect().width() - (DEFAULT_TICK_PADDING * 2), height, color); +} + +int HighlightedScrollBar::posToScrollBarY(int pos) const +{ + int line = editor->visibleFromDocLine(editor->lineFromPosition(pos)); + + return lineToScrollBarY(line); +} + +int HighlightedScrollBar::lineToScrollBarY(int line) const +{ + int lineCount = editor->visibleFromDocLine(editor->lineCount()); + + if (!editor->endAtLastLine()) { + lineCount += editor->linesOnScreen(); + } + + return static_cast(line) / lineCount * (rect().height() - scrollbarArrowHeight() * 2); +} + +int HighlightedScrollBar::scrollbarArrowHeight() const +{ + // NOTE: There is no official way to get the height of the scrollbar arrow buttons, however for now we can + // assume that the buttons are square, meaning the height of them will be the same as the width of + // the scroll bar. + return rect().width(); +} diff --git a/src/NotepadNext/decorators/HighlightedScrollBar.h b/src/NotepadNext/decorators/HighlightedScrollBar.h new file mode 100644 index 000000000..c31522046 --- /dev/null +++ b/src/NotepadNext/decorators/HighlightedScrollBar.h @@ -0,0 +1,72 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef HIGHLIGHTEDSCROLLBAR_H +#define HIGHLIGHTEDSCROLLBAR_H + +#include +#include + +#include "EditorDecorator.h" + + +class HighlightedScrollBar; + +class HighlightedScrollBarDecorator : public EditorDecorator +{ + Q_OBJECT + +public: + explicit HighlightedScrollBarDecorator(ScintillaNext *editor); + ~HighlightedScrollBarDecorator() override; + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; + +private: + HighlightedScrollBar *scrollBar; +}; + + +class HighlightedScrollBar : public QScrollBar +{ + Q_OBJECT + +public: + explicit HighlightedScrollBar(ScintillaNext *editor, Qt::Orientation orientation, QWidget *parent = nullptr); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + void drawMarker(QPainter &p, int marker); + void drawIndicator(QPainter &p, int indicator); + void drawCursors(QPainter &p); + + void drawTickMark(QPainter &p, int y, int height, QColor color); + + int posToScrollBarY(int pos) const; + int lineToScrollBarY(int line) const; + int scrollbarArrowHeight() const; + + ScintillaNext *editor; + int smartHighlighterIndicator; +}; + +#endif // HIGHLIGHTEDSCROLLBAR_H diff --git a/src/NotepadNext/decorators/LineNumbers.cpp b/src/NotepadNext/decorators/LineNumbers.cpp new file mode 100644 index 000000000..bf3af741d --- /dev/null +++ b/src/NotepadNext/decorators/LineNumbers.cpp @@ -0,0 +1,66 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "LineNumbers.h" + +using namespace Scintilla; + +static inline int countDigits(quint32 x) +{ + // Ugly but efficient + return (x < 10 ? 1 : + (x < 100 ? 2 : + (x < 1000 ? 3 : + (x < 10000 ? 4 : + (x < 100000 ? 5 : + (x < 1000000 ? 6 : + (x < 10000000 ? 7 : + (x < 100000000 ? 8 : + (x < 1000000000 ? 9 : + 10))))))))); +} + +LineNumbers::LineNumbers(ScintillaNext *editor) : + EditorDecorator(editor) +{ + editor->setMarginWidthN(0, 0); + + connect(this, &EditorDecorator::stateChanged, editor, [=](bool b) { + if (b) { + adjustMarginWidth(); + } + else { + editor->setMarginWidthN(0, 0); + } + }); +} + +void LineNumbers::adjustMarginWidth() +{ + int lineCount = editor->lineCount(); + int pixelWidth = 8 + (qMax(countDigits(lineCount), 3)) * editor->textWidth(STYLE_LINENUMBER, "8"); + editor->setMarginWidthN(0, pixelWidth); +} + +void LineNumbers::notify(const NotificationData *pscn) +{ + if ((pscn->nmhdr.code == Notification::UpdateUI && FlagSet(pscn->updated, Update::VScroll)) || (pscn->nmhdr.code == Notification::Zoom)) { + adjustMarginWidth(); + } +} diff --git a/src/NotepadNext/decorators/LineNumbers.h b/src/NotepadNext/decorators/LineNumbers.h new file mode 100644 index 000000000..96e0191ac --- /dev/null +++ b/src/NotepadNext/decorators/LineNumbers.h @@ -0,0 +1,41 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef LINENUMBERS_H +#define LINENUMBERS_H + +#include + +#include "EditorDecorator.h" + +class LineNumbers : public EditorDecorator +{ + Q_OBJECT + +public: + LineNumbers(ScintillaNext *editor); + +private: + void adjustMarginWidth(); + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; +}; + +#endif // LINENUMBERS_H diff --git a/src/NotepadNext/decorators/SmartHighlighter.cpp b/src/NotepadNext/decorators/SmartHighlighter.cpp new file mode 100644 index 000000000..9924e63cd --- /dev/null +++ b/src/NotepadNext/decorators/SmartHighlighter.cpp @@ -0,0 +1,94 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "SmartHighlighter.h" + +using namespace Scintilla; + + +SmartHighlighter::SmartHighlighter(ScintillaNext *editor) : + EditorDecorator(editor) +{ + setObjectName("SmartHighlighter"); + + indicator = editor->allocateIndicator("smart_highlighter"); + + editor->indicSetFore(indicator, 0x00FF00); + editor->indicSetStyle(indicator, INDIC_ROUNDBOX); + editor->indicSetOutlineAlpha(indicator, 150); + editor->indicSetAlpha(indicator, 100); + editor->indicSetUnder(indicator, true); +} + +void SmartHighlighter::notify(const NotificationData *pscn) +{ + if (pscn->nmhdr.code == Notification::UpdateUI && (FlagSet(pscn->updated, Update::Content) || FlagSet(pscn->updated, Update::Selection))) { + highlightCurrentView(); + } +} + +void SmartHighlighter::highlightCurrentView() +{ + editor->setIndicatorCurrent(indicator); + editor->indicatorClearRange(0, editor->length()); + + if (editor->selectionEmpty()) { + return; + } + + const int mainSelection = editor->mainSelection(); + const int selectionStart = editor->selectionNStart(mainSelection); + const int selectionEnd = editor->selectionNEnd(mainSelection); + + // Make sure the current selection is valid + if (selectionStart == selectionEnd) { + return; + } + + const int curPos = editor->currentPos(); + const int wordStart = editor->wordStartPosition(curPos, true); + const int wordEnd = editor->wordEndPosition(wordStart, true); + + // Make sure the selection is on word boundaries + if (wordStart == wordEnd || wordStart != selectionStart || wordEnd != selectionEnd) { + return; + } + + const QByteArray selText = editor->get_text_range(selectionStart, selectionEnd); + + // TODO: Handle large files. By default Notepad++ only monitors the text on screen. However, + // that will not work when using a highlighted scroll bar. Testing with small files seems to + // have minimal impact. For large files, Qt can have a timer set to 0 to do heavier processing. + // Using threads seems to be a bit overkill and too burdensome to do it properly. + + //const int startLine = editor->firstVisibleLine(); + //const int linesOnScreen = editor->linesOnScreen(); + //const int startPos = editor->positionFromLine(startLine); + //const int endPos = editor->lineEndPosition(startLine + linesOnScreen); + + // TODO: skip hidden or folded lines? + + Sci_TextToFind ttf {{0, (Sci_PositionCR)editor->length()}, selText.constData(), {-1, -1}}; + const int flags = SCFIND_MATCHCASE | SCFIND_WHOLEWORD; + + while (editor->send(SCI_FINDTEXT, flags, (sptr_t)&ttf) != -1) { + editor->indicatorFillRange(ttf.chrgText.cpMin, ttf.chrgText.cpMax - ttf.chrgText.cpMin); + ttf.chrg.cpMin = ttf.chrgText.cpMax; + } +} diff --git a/src/NotepadNext/decorators/SmartHighlighter.h b/src/NotepadNext/decorators/SmartHighlighter.h new file mode 100644 index 000000000..679657d25 --- /dev/null +++ b/src/NotepadNext/decorators/SmartHighlighter.h @@ -0,0 +1,41 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SMARTHIGHLIGHTER_H +#define SMARTHIGHLIGHTER_H + +#include "EditorDecorator.h" + + +class SmartHighlighter : public EditorDecorator +{ + Q_OBJECT + +public: + SmartHighlighter(ScintillaNext *editor); + +private: + void highlightCurrentView(); + int indicator; + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; +}; + +#endif // SMARTHIGHLIGHTER_H diff --git a/src/NotepadNext/decorators/SurroundSelection.cpp b/src/NotepadNext/decorators/SurroundSelection.cpp new file mode 100644 index 000000000..09fe09594 --- /dev/null +++ b/src/NotepadNext/decorators/SurroundSelection.cpp @@ -0,0 +1,118 @@ +/* + * This file is part of Notepad Next. + * Copyright 2020 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "SurroundSelection.h" + +#include +#include + + +SurroundSelection::SurroundSelection(ScintillaNext *editor) : + EditorDecorator(editor) +{ + setObjectName("SurroundSelection"); + + editor->installEventFilter(this); +} + +bool SurroundSelection::eventFilter(QObject *obj, QEvent *event) +{ + Q_UNUSED(obj) + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (editor->selectionEmpty() == false) { + switch (keyEvent->key()) { + case Qt::Key_Apostrophe: + surroundSelections('\'', '\''); + return true; + case Qt::Key_QuoteDbl: + surroundSelections('"', '"'); + return true; + case Qt::Key_QuoteLeft: + surroundSelections('`', '`'); + return true; + case Qt::Key_ParenLeft: + case Qt::Key_ParenRight: + surroundSelections('(', ')'); + return true; + case Qt::Key_BraceLeft: + case Qt::Key_BraceRight: + surroundSelections('{', '}'); + return true; + case Qt::Key_BracketLeft: + case Qt::Key_BracketRight: + surroundSelections('[', ']'); + return true; + } + } + } + + return false; +} + + +void SurroundSelection::notify(const Scintilla::NotificationData *pscn) +{ + Q_UNUSED(pscn) +} + +void SurroundSelection::surroundSelections(const char ch1, const char ch2) +{ + std::vector> selections; + + int num = editor->selections(); + for (int i = 0; i < num; ++i) { + int start = editor->selectionNStart(i); + int end = editor->selectionNEnd(i); + + if (start != end /* && editor.LineFromPosition(start) == editor.LineFromPosition(end) */) + selections.push_back(std::make_pair(start, end)); + } + + // Sort so they are replaced top to bottom + std::sort(selections.begin(), selections.end()); + + editor->beginUndoAction(); + editor->clearSelections(); + + int offset = 0; + for (size_t i = 0; i < selections.size(); ++i) { + const auto &selection = selections[i]; + editor->setTargetRange(selection.first + offset, selection.second + offset); + + QByteArray target = editor->targetText(); + + // Add in the characters + target.push_front(ch1); + target.push_back(ch2); + + editor->replaceTarget(target.length(), target.data()); + + // leave cursor at end of insertion + if (i == 0) + editor->setSelection(selection.second + offset + 1, selection.first + offset + 1); + else + editor->addSelection(selection.second + offset + 1, selection.first + offset + 1); + + offset += 2; // Add 2 since the replaced string is 2 chars longer + } + + editor->endUndoAction(); +} diff --git a/src/NotepadNext/decorators/SurroundSelection.h b/src/NotepadNext/decorators/SurroundSelection.h new file mode 100644 index 000000000..6feaf4a44 --- /dev/null +++ b/src/NotepadNext/decorators/SurroundSelection.h @@ -0,0 +1,46 @@ +/* + * This file is part of Notepad Next. + * Copyright 2020 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SURROUNDSELECTION_H +#define SURROUNDSELECTION_H + +#include +#include + +#include "EditorDecorator.h" + + +class SurroundSelection : public EditorDecorator +{ + Q_OBJECT + +public: + SurroundSelection(ScintillaNext *editor); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; + +private: + void surroundSelections(const char ch1, const char ch2); +}; + +#endif // SURROUNDSELECTION_H diff --git a/src/NotepadNext/decorators/URLFinder.cpp b/src/NotepadNext/decorators/URLFinder.cpp new file mode 100644 index 000000000..56e9e4c8a --- /dev/null +++ b/src/NotepadNext/decorators/URLFinder.cpp @@ -0,0 +1,166 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include +#include +#include + +#include "URLFinder.h" + + +URLFinder::URLFinder(ScintillaNext *editor) : + EditorDecorator(editor), + timer(new QTimer(this)) +{ + // Setup the indicator + indicator = editor->allocateIndicator("url_finder"); + + editor->indicSetStyle(indicator, INDIC_PLAIN); + editor->indicSetFore(indicator, 0xFF0000); + + editor->indicSetHoverStyle(indicator, INDIC_DOTS); + editor->indicSetHoverFore(indicator, 0xFF0000); + + // Resizing the window could reveal more text + connect(editor, &ScintillaNext::resized, timer, qOverload<>(&QTimer::start)); + + timer->setInterval(200); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, this, &URLFinder::findURLs); +} + +void URLFinder::findURLs() +{ + //qInfo(Q_FUNC_INFO); + + editor->setIndicatorCurrent(indicator); + editor->indicatorClearRange(0, editor->length()); + + int currentLine = editor->docLineFromVisible(editor->firstVisibleLine()); + int linesLeftToProcess = editor->linesOnScreen(); + const int flags = SCFIND_REGEXP; + + while(linesLeftToProcess >= 0 && currentLine < editor->lineCount()) { + // Should only happen if the line is hidden + if (!editor->lineVisible(currentLine)) { + currentLine++; + continue; + } + + const int startPos = editor->positionFromLine(currentLine); + const int endPos = editor->lineEndPosition(currentLine); + QByteArray reg = QByteArrayLiteral(R"(\bhttps?://[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*))"); + + Sci_TextToFind ttf {{startPos, (Sci_PositionCR)endPos}, reg.constData(), {-1, -1}}; + while (editor->send(SCI_FINDTEXT, flags, (sptr_t)&ttf) != -1) { + const int startUrl = ttf.chrgText.cpMin; + int endUrl = ttf.chrgText.cpMax; + + // Though technically certain characters are allowed in the URL such as brackets, parenthesis, etc + // this adds a bit of logic to trim off the end character based on if something is in front if it, for example + // [https://example.com] probably shouldn't include the last bracket since it starts with an opening bracket. + if (startUrl > 0) { + const int prevChar = static_cast(editor->charAt(startUrl - 1)); + const int nextChar = static_cast(editor->charAt(endUrl - 1)); + + if ((prevChar == '(' && nextChar == ')') || + (prevChar == '[' && nextChar == ']') || + (prevChar == '<' && nextChar == '>') || + (prevChar == '"' && nextChar == '"')) { + endUrl--; + } + } + + editor->indicatorFillRange(startUrl, endUrl - startUrl); + ttf.chrg.cpMin = endUrl; + } + + // If a line is wrapped, skip however many lines it takes up on the screen + linesLeftToProcess -= editor->wrapCount(currentLine); + + // If the current line is a fold header and the fold is not expanded, skip + if (((editor->foldLevel(currentLine) & SC_FOLDLEVELHEADERFLAG) == SC_FOLDLEVELHEADERFLAG) && (!editor->foldExpanded(currentLine))) { + currentLine = editor->lastChild(currentLine, -1) + 1; + } + else { + currentLine++; + } + } +} + +void URLFinder::notify(const Scintilla::NotificationData *pscn) +{ + // TODO: handle editor folding/unfolding + // Currently there is no generic notification for this + + // Reprocess any time the content was updated or the editor was vertically scrolled + if ((pscn->nmhdr.code == Scintilla::Notification::UpdateUI)) { + if (FlagSet(pscn->updated, Scintilla::Update::VScroll)) { + timer->start(); + } + } + else if (pscn->nmhdr.code == Scintilla::Notification::Modified) { + if (FlagSet(pscn->modificationType, Scintilla::ModificationFlags::InsertText) || FlagSet(pscn->modificationType, Scintilla::ModificationFlags::DeleteText)) { + timer->start(); + } + } + else if (pscn->nmhdr.code == Scintilla::Notification::Zoom) { + timer->start(); + } + else if (pscn->nmhdr.code == Scintilla::Notification::IndicatorClick && FlagSet(pscn->modifiers, Scintilla::KeyMod::Ctrl)) { + const int indicators = editor->indicatorAllOnFor(pscn->position); + + if (indicators & (1 << indicator)) { + + const int indicatorStart = editor->indicatorStart(indicator, pscn->position); + const int indicatorEnd = editor->indicatorEnd(indicator, pscn->position); + + QUrl url(editor->get_text_range(indicatorStart, indicatorEnd)); + + if (url.isValid()) { + qInfo("URL hotspot click: \"%s\"", editor->get_text_range(indicatorStart, indicatorEnd).constData()); + QDesktopServices::openUrl(url); + } + else { + qWarning("Invalid url \"%s\"", qUtf8Printable(url.errorString())); + } + } + } +} + +bool URLFinder::isURL(int position) const +{ + const int indicators = editor->indicatorAllOnFor(position); + return indicators & (1 << indicator); +} + +void URLFinder::copyURLToClipboard(int position) const +{ + const int indicatorStart = editor->indicatorStart(indicator, position); + const int indicatorEnd = editor->indicatorEnd(indicator, position); + + QUrl url(editor->get_text_range(indicatorStart, indicatorEnd)); + + if (url.isValid()) { + qInfo("Copy URL to clipboard: \"%s\"", editor->get_text_range(indicatorStart, indicatorEnd).constData()); + editor->copyRange(indicatorStart, indicatorEnd); + } + else { + qWarning("Invalid url \"%s\"", qUtf8Printable(url.errorString())); + } +} diff --git a/src/NotepadNext/decorators/URLFinder.h b/src/NotepadNext/decorators/URLFinder.h new file mode 100644 index 000000000..e628e7b76 --- /dev/null +++ b/src/NotepadNext/decorators/URLFinder.h @@ -0,0 +1,45 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef URLFINDER_H +#define URLFINDER_H + +#include "EditorDecorator.h" + +class URLFinder : public EditorDecorator +{ + Q_OBJECT + +public: + URLFinder(ScintillaNext *editor); + bool isURL(int position) const; + void copyURLToClipboard(int position) const; + +private slots: + void findURLs(); + +public slots: + void notify(const Scintilla::NotificationData *pscn) override; + +private: + QTimer *timer; + int indicator; +}; + +#endif // URLFINDER_H diff --git a/src/NotepadNext/dialogs/ColumnEditorDialog.cpp b/src/NotepadNext/dialogs/ColumnEditorDialog.cpp new file mode 100644 index 000000000..3f4aa5618 --- /dev/null +++ b/src/NotepadNext/dialogs/ColumnEditorDialog.cpp @@ -0,0 +1,120 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "ColumnEditorDialog.h" +#include "UndoAction.h" +#include "ui_ColumnEditorDialog.h" + + +ColumnEditorDialog::ColumnEditorDialog(MainWindow *parent) : + QDialog(parent), + ui(new Ui::ColumnEditorDialog), + parent(parent) +{ + setWindowFlag(Qt::WindowContextHelpButtonHint, false); + + ui->setupUi(this); + + ui->sbxStart->setMaximum(std::numeric_limits::max()); + ui->sbxStart->setMinimum(std::numeric_limits::min()); + + ui->sbxStep->setMaximum(std::numeric_limits::max()); + ui->sbxStep->setMinimum(std::numeric_limits::min()); + + connect(ui->gbxText, &QGroupBox::toggled, ui->gbxNumbers, [=](bool on) { + ui->gbxNumbers->setChecked(!on); + }); + + connect(ui->gbxNumbers, &QGroupBox::toggled, ui->gbxText, [=](bool on) { + ui->gbxText->setChecked(!on); + }); + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, [=]() { + if (ui->gbxText->isChecked() && !ui->txtText->text().isEmpty()) { + insertTextStartingAtCurrentColumn([=]() { return ui->txtText->text(); }); + } + else if (ui->gbxNumbers->isChecked()) { + int currentValue = ui->sbxStart->value(); + insertTextStartingAtCurrentColumn([¤tValue, this]() { + const QString s = QString::number(currentValue); + currentValue += ui->sbxStep->value(); + return s; + }); + } + }); + + ui->txtText->setFocus(); +} + +ColumnEditorDialog::~ColumnEditorDialog() +{ + delete ui; +} + +void ColumnEditorDialog::insertTextStartingAtCurrentColumn(const std::function &f) +{ + ScintillaNext *editor = parent->currentEditor(); + + if (editor->selectionMode() == SC_SEL_STREAM && editor->selections() == 1 && editor->selectionEmpty()) { + const int currentPos = editor->selectionNCaret(0); + + // If the cursor is in virtual space, the call to selectionNCaretVirtualSpace will be > 0 + const int currentColumn = editor->column(currentPos) + editor->selectionNCaretVirtualSpace(0); + + const UndoAction ua(editor); + for (int line = editor->lineFromPosition(currentPos); line < editor->lineCount(); ++line) { + insertTextAtColumn(editor, line, currentColumn, f()); + } + } + else/* if (editor->selectionMode() == SC_SEL_RECTANGLE || editor->selections() > 0)*/ { + const int totalSelections = editor->selections(); + + // TODO: sort selections from top to bottom? + + const UndoAction ua(editor); + for(int selection = 0; selection < totalSelections; ++selection) { + const int start = editor->selectionNStart(selection) + editor->selectionNStartVirtualSpace(selection); + const int end = editor->selectionNEnd(selection) + editor->selectionNEndVirtualSpace(selection); + + editor->setTargetRange(start, end); + editor->replaceTarget(-1, f().toUtf8().constData()); + } + } +} + +void ColumnEditorDialog::insertTextAtColumn(ScintillaNext *editor, int line, int column, const QString &str) +{ + const int lineEndPosition = editor->lineEndPosition(line); + const int lineEndColumn = editor->column(lineEndPosition); + + // If the line does not end past the needed column, then use the left over as virtual space + if (lineEndColumn < column) { + editor->setTargetRange(lineEndPosition, lineEndPosition); + + editor->setTargetStartVirtualSpace(column - lineEndColumn); + editor->setTargetEndVirtualSpace(column - lineEndColumn); + } + else { + const int pos = editor->findColumn(line, column); + + editor->setTargetRange(pos, pos); + } + + editor->replaceTarget(-1, str.toUtf8().constData()); +} diff --git a/src/NotepadNext/dialogs/ColumnEditorDialog.h b/src/NotepadNext/dialogs/ColumnEditorDialog.h new file mode 100644 index 000000000..cb6a28062 --- /dev/null +++ b/src/NotepadNext/dialogs/ColumnEditorDialog.h @@ -0,0 +1,46 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef COLUMNEDITORDIALOG_H +#define COLUMNEDITORDIALOG_H + +#include "MainWindow.h" +#include + +namespace Ui { +class ColumnEditorDialog; +} + +class ColumnEditorDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ColumnEditorDialog(MainWindow *parent); + ~ColumnEditorDialog(); + + void insertTextStartingAtCurrentColumn(const std::function & f); + void insertTextAtColumn(ScintillaNext *editor, int line, int column, const QString &str); + +private: + Ui::ColumnEditorDialog *ui; + MainWindow *parent; +}; + +#endif // COLUMNEDITORDIALOG_H diff --git a/src/NotepadNext/dialogs/ColumnEditorDialog.ui b/src/NotepadNext/dialogs/ColumnEditorDialog.ui new file mode 100644 index 000000000..be47e89f1 --- /dev/null +++ b/src/NotepadNext/dialogs/ColumnEditorDialog.ui @@ -0,0 +1,153 @@ + + + ColumnEditorDialog + + + + 0 + 0 + 400 + 249 + + + + + 0 + 0 + + + + Column Mode + + + false + + + false + + + + + + Text + + + true + + + + + + + + + + + + Numbers + + + true + + + false + + + + + + Start: + + + + + + + QAbstractSpinBox::NoButtons + + + 1 + + + + + + + Step: + + + + + + + QAbstractSpinBox::NoButtons + + + 1 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + ColumnEditorDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ColumnEditorDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/NotepadNext/dialogs/FindReplaceDialog.cpp b/src/NotepadNext/dialogs/FindReplaceDialog.cpp new file mode 100644 index 000000000..6f5ea611f --- /dev/null +++ b/src/NotepadNext/dialogs/FindReplaceDialog.cpp @@ -0,0 +1,621 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "FindReplaceDialog.h" +#include "ApplicationSettings.h" +#include "ui_FindReplaceDialog.h" + +#include +#include +#include + +#include "ScintillaNext.h" +#include "MainWindow.h" + + +static void convertToExtended(QString &str) +{ + str.replace("\\r", "\r"); + str.replace("\\n", "\n"); + str.replace("\\t", "\t"); + str.replace("\\0", "\0"); + str.replace("\\\\", "\\"); + // TODO: more +} + +FindReplaceDialog::FindReplaceDialog(ISearchResultsHandler *searchResults, MainWindow *window) : + QDialog(window, Qt::Dialog), + ui(new Ui::FindReplaceDialog), + searchResultsHandler(searchResults), + finder(new Finder(window->currentEditor())) +{ + qInfo(Q_FUNC_INFO); + + // Turn off the help button on the dialog + setWindowFlag(Qt::WindowContextHelpButtonHint, false); + ui->setupUi(this); + + // Get the current editor, and keep up the reference + setEditor(window->currentEditor()); + connect(window, &MainWindow::editorActivated, this, &FindReplaceDialog::setEditor); + + tabBar = new QTabBar(); + tabBar->addTab(tr("Find")); + tabBar->addTab(tr("Replace")); + tabBar->setExpanding(false); + qobject_cast(layout())->insertWidget(0, tabBar); + connect(tabBar, &QTabBar::currentChanged, this, &FindReplaceDialog::changeTab); + + statusBar = new QStatusBar(); + statusBar->setSizeGripEnabled(false); // the dialog has one already + qobject_cast(layout())->insertWidget(-1, statusBar); + + // Disable auto completion + ui->comboFind->setCompleter(nullptr); + ui->comboReplace->setCompleter(nullptr); + + // If the selection changes highlight the text + connect(ui->comboFind, static_cast(&QComboBox::currentIndexChanged), ui->comboFind->lineEdit(), &QLineEdit::selectAll); + connect(ui->comboReplace, static_cast(&QComboBox::currentIndexChanged), ui->comboReplace->lineEdit(), &QLineEdit::selectAll); + + // Force focus on the find text box + connect(this, &FindReplaceDialog::windowActivated, [=]() { + ui->comboFind->setFocus(); + ui->comboFind->lineEdit()->selectAll(); + }); + + connect(this, &QDialog::rejected, [=]() { + statusBar->clearMessage(); + savePosition(); + }); + + connect(ui->radioRegexSearch, &QRadioButton::toggled, this, [=](bool checked) { + ui->checkBoxBackwardsDirection->setDisabled(checked); + ui->checkBoxMatchWholeWord->setDisabled(checked); + ui->checkBoxRegexMatchesNewline->setEnabled(checked); + }); + + connect(ui->radioOnLosingFocus, &QRadioButton::toggled, this, &FindReplaceDialog::adjustOpacityWhenLosingFocus); + connect(ui->radioAlways, &QRadioButton::toggled, this, &FindReplaceDialog::adjustOpacityAlways); + connect(ui->transparency, &QGroupBox::toggled, this, &FindReplaceDialog::transparencyToggled); + + connect(ui->buttonFind, &QPushButton::clicked, this, &FindReplaceDialog::find); + connect(ui->buttonCount, &QPushButton::clicked, this, &FindReplaceDialog::count); + connect(ui->buttonFindAllInCurrent, &QPushButton::clicked, this, [=]() { + prepareToPerformSearch(); + + searchResultsHandler->newSearch(findString()); + + findAllInCurrentDocument(); + + searchResultsHandler->completeSearch(); + + close(); + }); + connect(ui->buttonFindAllInDocuments, &QPushButton::clicked, this, [=]() { + prepareToPerformSearch(); + + searchResultsHandler->newSearch(findString()); + + findAllInDocuments(); + + searchResultsHandler->completeSearch(); + + close(); + }); + connect(ui->buttonReplace, &QPushButton::clicked, this, &FindReplaceDialog::replace); + connect(ui->buttonReplaceAll, &QPushButton::clicked, this, &FindReplaceDialog::replaceAll); + connect(ui->buttonReplaceAllInDocuments, &QPushButton::clicked, this, [=]() { + prepareToPerformSearch(true); + + QString replaceText = replaceString(); + + if (ui->radioExtendedSearch->isChecked()) { + convertToExtended(replaceText); + } + + int count = 0; + ScintillaNext *current_editor = editor; + MainWindow *window = qobject_cast(parent()); + + for(ScintillaNext *editor : window->editors()) { + setEditor(editor); + count += finder->replaceAll(replaceText); + } + + setEditor(current_editor); + + showMessage(tr("Replaced %Ln matches", "", count), "green"); + }); + connect(ui->buttonClose, &QPushButton::clicked, this, &FindReplaceDialog::close); + + loadSettings(); + + connect(qApp, &QApplication::aboutToQuit, this, &FindReplaceDialog::saveSettings); + + changeTab(tabBar->currentIndex()); + +} + +FindReplaceDialog::~FindReplaceDialog() +{ + delete ui; + delete finder; +} + +void FindReplaceDialog::setFindString(const QString &string) +{ + ui->comboFind->setCurrentText(string); + ui->comboFind->lineEdit()->selectAll(); +} + +void FindReplaceDialog::setTab(int tab) +{ + tabBar->setCurrentIndex(tab); +} + +bool FindReplaceDialog::event(QEvent *event) +{ + if (event->type() == QEvent::WindowActivate) { + emit windowActivated(); + } + else if (event->type() == QEvent::WindowDeactivate) { + emit windowDeactivated(); + } + + return QDialog::event(event); +} + +void FindReplaceDialog::showEvent(QShowEvent *event) +{ + qInfo(Q_FUNC_INFO); + + if (!isFirstTime) + restorePosition(); + + isFirstTime = false; + + QDialog::showEvent(event); +} + +static void updateComboList(QComboBox *comboBox, const QString &text) +{ + // Block the signals while it is manipulated + const QSignalBlocker blocker(comboBox); + + // Remove it if it is in the list, add it to beginning, and select it + comboBox->removeItem(comboBox->findText(text)); + comboBox->insertItem(0, text); + comboBox->setCurrentIndex(0); +} + +void FindReplaceDialog::updateFindList(const QString &text) +{ + if (!text.isEmpty()) + updateComboList(ui->comboFind, text); +} + +void FindReplaceDialog::updateReplaceList(const QString &text) +{ + updateComboList(ui->comboReplace, text); +} + +void FindReplaceDialog::find() +{ + qInfo(Q_FUNC_INFO); + + prepareToPerformSearch(); + + Sci_CharacterRange range; + if(!ui->checkBoxBackwardsDirection->isChecked()) { + range = finder->findNext(); + } + else{ + range = finder->findPrev(); + } + + if (ScintillaNext::isRangeValid(range)) { + if (finder->didLatestSearchWrapAround()) { + showMessage(tr("The end of the document has been reached. Found 1st occurrence from the top."), "green"); + } + + // TODO: Handle zero length matches better + if (range.cpMin == range.cpMax) { + qWarning() << "0 length match at" << range.cpMin; + } + + editor->goToRange(range); + } + else { + showMessage(tr("No matches found."), "red"); + } +} + +void FindReplaceDialog::findAllInCurrentDocument() +{ + qInfo(Q_FUNC_INFO); + + bool firstMatch = true; + + QString text = findString(); + + finder->setSearchText(text); + finder->forEachMatch([&](int start, int end){ + // Only add the file entry if there was a valid search result + if (firstMatch) { + searchResultsHandler->newFileEntry(editor); + firstMatch = false; + } + + const int line = editor->lineFromPosition(start); + const int lineStartPosition = editor->positionFromLine(line); + const int lineEndPosition = editor->lineEndPosition(line); + const int startPositionFromBeginning = start - lineStartPosition; + const int endPositionFromBeginning = end - lineStartPosition; + QString lineText = editor->get_text_range(lineStartPosition, lineEndPosition); + + searchResultsHandler->newResultsEntry(lineText, line, startPositionFromBeginning, endPositionFromBeginning); + + return end; + }); +} + +void FindReplaceDialog::findAllInDocuments() +{ + qInfo(Q_FUNC_INFO); + + ScintillaNext *current_editor = editor; + MainWindow *window = qobject_cast(parent()); + + for(ScintillaNext *editor : window->editors()) { + setEditor(editor); + findAllInCurrentDocument(); + } + + setEditor(current_editor); +} + +void FindReplaceDialog::replace() +{ + qInfo(Q_FUNC_INFO); + + prepareToPerformSearch(); + + QString replaceText = replaceString(); + + if (ui->radioExtendedSearch->isChecked()) { + convertToExtended(replaceText); + } + + Sci_CharacterRange range = finder->replaceSelectionIfMatch(replaceText); + + if (ScintillaNext::isRangeValid(range)) { + showMessage(tr("1 occurrence was replaced"), "blue"); + } + + Sci_CharacterRange next_match = finder->findNext(); + + if (ScintillaNext::isRangeValid(next_match)) { + editor->goToRange(next_match); + } + else { + showMessage(tr("No more occurrences were found"), "red"); + ui->comboFind->setFocus(); + ui->comboFind->lineEdit()->selectAll(); + } +} + +void FindReplaceDialog::replaceAll() +{ + qInfo(Q_FUNC_INFO); + + prepareToPerformSearch(true); + + QString replaceText = replaceString(); + + if (ui->radioExtendedSearch->isChecked()) { + convertToExtended(replaceText); + } + + int count = finder->replaceAll(replaceText); + showMessage(tr("Replaced %Ln matches", "", count), "green"); +} + +void FindReplaceDialog::count() +{ + qInfo(Q_FUNC_INFO); + + prepareToPerformSearch(); + + int total = finder->count(); + + showMessage(tr("Found %Ln matches", "", total), "green"); +} + +void FindReplaceDialog::setEditor(ScintillaNext *editor) +{ + this->editor = editor; + + finder->setEditor(editor); +} + +void FindReplaceDialog::performLastSearch() +{ + editor->goToRange(finder->findNext()); +} + +void FindReplaceDialog::adjustOpacity(int value) +{ + qInfo(Q_FUNC_INFO); + + setWindowOpacity(value * .01); +} + +void FindReplaceDialog::transparencyToggled(bool on) +{ + qInfo(Q_FUNC_INFO); + + if (on) { + if (ui->radioOnLosingFocus->isChecked()) { + adjustOpacityWhenLosingFocus(true); + adjustOpacityAlways(false); + } + else { + adjustOpacityWhenLosingFocus(false); + adjustOpacityAlways(true); + } + } + else { + adjustOpacityWhenLosingFocus(false); + adjustOpacityAlways(false); + adjustOpacity(100); + } +} + +void FindReplaceDialog::adjustOpacityWhenLosingFocus(bool checked) +{ + qInfo(Q_FUNC_INFO); + + if (checked) { + connect(this, &FindReplaceDialog::windowActivated, [=]() { + this->adjustOpacity(100); + }); + connect(this, &FindReplaceDialog::windowDeactivated, [=]() { + this->adjustOpacity(ui->horizontalSlider->value()); + }); + adjustOpacity(100); + } + else { + disconnect(this, &FindReplaceDialog::windowActivated, nullptr, nullptr); + disconnect(this, &FindReplaceDialog::windowDeactivated, nullptr, nullptr); + } +} + +void FindReplaceDialog::adjustOpacityAlways(bool checked) +{ + qInfo(Q_FUNC_INFO); + + if (checked) { + connect(ui->horizontalSlider, &QSlider::valueChanged, this, &FindReplaceDialog::adjustOpacity); + adjustOpacity(ui->horizontalSlider->value()); + } + else { + disconnect(ui->horizontalSlider, &QSlider::valueChanged, this, &FindReplaceDialog::adjustOpacity); + } +} + +void FindReplaceDialog::changeTab(int index) +{ + if (index == 0) { + ui->labelReplaceWith->setMaximumHeight(0); + ui->comboReplace->setMaximumHeight(0); + // The combo box isn't actually "hidden", so adjust the focus policy so it does not get tabbed to + ui->comboReplace->setFocusPolicy(Qt::NoFocus); + + ui->buttonReplace->hide(); + ui->buttonReplaceAll->hide(); + ui->buttonReplaceAllInDocuments->hide(); + + ui->buttonCount->show(); + ui->buttonFindAllInCurrent->show(); + ui->buttonFindAllInDocuments->show(); + } + else if (index == 1) { + ui->labelReplaceWith->setMaximumHeight(QWIDGETSIZE_MAX); + ui->comboReplace->setMaximumHeight(QWIDGETSIZE_MAX); + ui->comboReplace->setFocusPolicy(Qt::StrongFocus); // Reset its focus policy + + ui->buttonReplace->show(); + ui->buttonReplaceAll->show(); + ui->buttonReplaceAllInDocuments->show(); + + ui->buttonCount->hide(); + ui->buttonFindAllInCurrent->hide(); + ui->buttonFindAllInDocuments->hide(); + } + + ui->comboFind->setFocus(); + ui->comboFind->lineEdit()->selectAll(); +} + +QString FindReplaceDialog::findString() +{ + return ui->comboFind->currentText(); +} + +QString FindReplaceDialog::replaceString() +{ + return ui->comboReplace->currentText(); +} + +void FindReplaceDialog::setSearchResultsHandler(ISearchResultsHandler *searchResults) +{ + this->searchResultsHandler = searchResults; +} + +void FindReplaceDialog::prepareToPerformSearch(bool replace) +{ + qInfo(Q_FUNC_INFO); + + QString findText = findString(); + + updateFindList(findText); + if (replace) { + QString replaceText = replaceString(); + updateReplaceList(replaceText); + } + + statusBar->clearMessage(); + + if (ui->radioExtendedSearch->isChecked()) { + convertToExtended(findText); + //convertToExtended(replaceText); + } + + finder->setWrap(ui->checkBoxWrapAround->isChecked()); + finder->setSearchFlags(computeSearchFlags()); + finder->setSearchText(findText); +} + +void FindReplaceDialog::loadSettings() +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings settings; + + settings.beginGroup("FindReplaceDialog"); + + ui->comboFind->addItems(settings.value("RecentSearchList").toStringList()); + ui->comboReplace->addItems(settings.value("RecentReplaceList").toStringList()); + + ui->checkBoxBackwardsDirection->setChecked(settings.value("Backwards").toBool()); + ui->checkBoxMatchWholeWord->setChecked(settings.value("WholeWord").toBool()); + ui->checkBoxMatchCase->setChecked(settings.value("MatchCase").toBool()); + ui->checkBoxWrapAround->setChecked(settings.value("WrapAround", true).toBool()); + + if (settings.contains("SearchMode")) { + const QString searchMode = settings.value("SearchMode").toString(); + if (searchMode == "normal") + ui->radioNormalSearch->setChecked(true); + else if (searchMode == "extended") + ui->radioExtendedSearch->setChecked(true); + else + ui->radioRegexSearch->setChecked(true); + } + ui->checkBoxRegexMatchesNewline->setChecked(settings.value("DotMatchesNewline").toBool()); + + ui->transparency->setChecked(settings.value("TransparencyUsed").toBool()); + if (ui->transparency->isChecked()) { + ui->horizontalSlider->setValue(settings.value("Transparency", 70).toInt()); + + if (settings.value("TransparencyMode").toString() == "focus") { + ui->radioOnLosingFocus->setChecked(true); + } + else { + ui->radioAlways->setChecked(true); + } + } + + settings.endGroup(); +} + +void FindReplaceDialog::saveSettings() +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings settings; + + settings.beginGroup("FindReplaceDialog"); + settings.remove(""); // clear out any previous keys + + QStringList recentSearches; + for (int i = 0; i < ui->comboFind->count(); ++i) { + recentSearches << ui->comboFind->itemText(i); + } + settings.setValue("RecentSearchList", recentSearches); + + recentSearches.clear(); + for (int i = 0; i < ui->comboReplace->count(); ++i) { + recentSearches << ui->comboReplace->itemText(i); + } + settings.setValue("RecentReplaceList", recentSearches); + + settings.setValue("Backwards", ui->checkBoxBackwardsDirection->isChecked()); + settings.setValue("WholeWord", ui->checkBoxMatchWholeWord->isChecked()); + settings.setValue("MatchCase", ui->checkBoxMatchCase->isChecked()); + settings.setValue("WrapAround", ui->checkBoxWrapAround->isChecked()); + + if (ui->radioNormalSearch->isChecked()) + settings.setValue("SearchMode", "normal"); + else if (ui->radioExtendedSearch->isChecked()) + settings.setValue("SearchMode", "extended"); + else if (ui->radioRegexSearch->isChecked()) + settings.setValue("SearchMode", "regex"); + settings.setValue("DotMatchesNewline", ui->checkBoxRegexMatchesNewline->isChecked()); + + settings.setValue("TransparencyUsed", ui->transparency->isChecked()); + if (ui->transparency->isChecked()) { + settings.setValue("Transparency", ui->horizontalSlider->value()); + settings.setValue("TransparencyMode", ui->radioOnLosingFocus->isChecked() ? "focus" : "always"); + } + + settings.endGroup(); +} + +void FindReplaceDialog::savePosition() +{ + qInfo(Q_FUNC_INFO); + + lastClosedPosition = pos(); +} + +void FindReplaceDialog::restorePosition() +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings settings; + + if (settings.centerSearchDialog()) { + const QPoint centerPoint = parentWidget()->geometry().center(); + move(centerPoint - rect().center()); + } + else { + move(lastClosedPosition); + } +} + +int FindReplaceDialog::computeSearchFlags() +{ + int flags = 0; + + if (ui->checkBoxMatchWholeWord->isChecked()) + flags |= SCFIND_WHOLEWORD; + if (ui->checkBoxMatchCase->isChecked()) + flags |= SCFIND_MATCHCASE; + if (ui->radioRegexSearch->isChecked()) + flags |= SCFIND_REGEXP; + + return flags; +} + +void FindReplaceDialog::showMessage(const QString &message, const QString &color) +{ + statusBar->setStyleSheet(QStringLiteral("color: %1").arg(color)); + statusBar->showMessage(message); +} diff --git a/src/NotepadNext/dialogs/FindReplaceDialog.h b/src/NotepadNext/dialogs/FindReplaceDialog.h new file mode 100644 index 000000000..4ae5505ec --- /dev/null +++ b/src/NotepadNext/dialogs/FindReplaceDialog.h @@ -0,0 +1,115 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef FINDREPLACEDIALOG_H +#define FINDREPLACEDIALOG_H + +#include +#include +#include +#include + +#include "Finder.h" +#include "ISearchResultsHandler.h" + + +class ScintillaNext; +class MainWindow; + +namespace Ui { +class FindReplaceDialog; +} + +class FindReplaceDialog : public QDialog +{ + Q_OBJECT + +public: + enum { + FIND_TAB = 0, + REPLACE_TAB = 1, + FIND_IN_FILES_TAB = 2, + MARK_TAB = 3 + }; + + explicit FindReplaceDialog(ISearchResultsHandler *searchResults, MainWindow *window = nullptr); + ~FindReplaceDialog() override; + + void setFindString(const QString &string); + void setTab(int tab); + + QString replaceString(); + + void setSearchResultsHandler(ISearchResultsHandler *searchResultsHandler); + +protected: + bool event(QEvent *event) override; + void showEvent(QShowEvent *event) override; + +signals: + void windowActivated(); + void windowDeactivated(); + +public slots: + void performLastSearch(); + + void find(); + void findAllInCurrentDocument(); + void findAllInDocuments(); + void count(); + void replace(); + void replaceAll(); + +private slots: + void setEditor(ScintillaNext *edit); + void adjustOpacity(int value); + void transparencyToggled(bool on); + void adjustOpacityWhenLosingFocus(bool checked); + void adjustOpacityAlways(bool on); + + void changeTab(int index); + +private: + QString findString(); + void prepareToPerformSearch(bool replace=false); + void loadSettings(); + void saveSettings(); + + void savePosition(); + void restorePosition(); + + int computeSearchFlags(); + + void showMessage(const QString &message, const QString &color); + + void updateFindList(const QString &text); + void updateReplaceList(const QString &text); + + bool isFirstTime = true; + QPoint lastClosedPosition; + Ui::FindReplaceDialog *ui; + + ScintillaNext *editor; + QStatusBar *statusBar; + QTabBar *tabBar; + ISearchResultsHandler *searchResultsHandler; + Finder *finder; +}; + +#endif // FINDREPLACEDIALOG_H diff --git a/src/NotepadNext/dialogs/FindReplaceDialog.ui b/src/NotepadNext/dialogs/FindReplaceDialog.ui new file mode 100644 index 000000000..fd09b5547 --- /dev/null +++ b/src/NotepadNext/dialogs/FindReplaceDialog.ui @@ -0,0 +1,509 @@ + + + FindReplaceDialog + + + + 0 + 0 + 600 + 325 + + + + + 475 + 325 + + + + + 16777215 + 325 + + + + Find + + + true + + + + 6 + + + QLayout::SetNoConstraint + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 6 + + + 0 + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Search Mode + + + + 4 + + + 4 + + + 4 + + + + + true + + + + 0 + 0 + + + + &Normal + + + true + + + + + + + + 0 + 0 + + + + E&xtended (\n, \r, \t, \0, \x...) + + + + + + + 16 + + + + + + 0 + 0 + + + + Re&gular expression + + + + + + + false + + + + 0 + 0 + + + + &. matches newline + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + + 175 + 0 + + + + Transparenc&y + + + true + + + false + + + + 4 + + + 4 + + + 4 + + + + + On losing focus + + + true + + + + + + + Always + + + + + + + 20 + + + 100 + + + 70 + + + Qt::Horizontal + + + + + + + + + + 6 + + + 12 + + + 6 + + + + + Find + + + false + + + true + + + + + + + Coun&t + + + false + + + + + + + &Replace + + + + + + + Replace &All + + + + + + + Replace All in &Opened Documents + + + + + + + Find All in All &Opened Documents + + + false + + + + + + + Find All in Current Document + + + false + + + + + + + Close + + + false + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 11 + + + 6 + + + 12 + + + + + QLayout::SetNoConstraint + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + Qt::AlignJustify|Qt::AlignTop + + + 8 + + + 8 + + + + + &Find: + + + comboFind + + + + + + + + 0 + 0 + + + + true + + + 10 + + + QComboBox::NoInsert + + + + + + + true + + + Replace: + + + + + + + + 0 + 0 + + + + true + + + 10 + + + QComboBox::NoInsert + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Backward direction + + + + + + + Match &whole word only + + + + + + + Match &case + + + + + + + Wra&p Around + + + + + + + + + + + comboFind + comboReplace + checkBoxBackwardsDirection + checkBoxMatchWholeWord + checkBoxMatchCase + checkBoxWrapAround + radioNormalSearch + radioExtendedSearch + radioRegexSearch + checkBoxRegexMatchesNewline + buttonFind + buttonCount + buttonReplace + buttonReplaceAll + buttonReplaceAllInDocuments + buttonFindAllInDocuments + buttonFindAllInCurrent + buttonClose + transparency + radioOnLosingFocus + radioAlways + horizontalSlider + + + + diff --git a/src/NotepadNext/dialogs/MacroEditorDialog.cpp b/src/NotepadNext/dialogs/MacroEditorDialog.cpp new file mode 100644 index 000000000..04d24528d --- /dev/null +++ b/src/NotepadNext/dialogs/MacroEditorDialog.cpp @@ -0,0 +1,206 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include +#include +#include + +#include "MacroEditorDialog.h" +#include "ComboBoxDelegate.h" + +#include "ui_MacroEditorDialog.h" + + +MacroEditorDialog::MacroEditorDialog(QWidget *parent, MacroManager *mm) : + QDialog(parent), + ui(new Ui::MacroEditorDialog), + macroManager(mm), + model(new MacroListModel(this, mm)) +{ + setWindowFlag(Qt::WindowContextHelpButtonHint, false); + + ui->setupUi(this); + + ui->listMacros->setModel(model); + + connect(ui->listMacros->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &MacroEditorDialog::rowChanged); + + connect(ui->btnCopyMacro, &QPushButton::clicked, this, &MacroEditorDialog::copyCurrentMacro); + connect(ui->btnDeleteMacro, &QPushButton::clicked, this, &MacroEditorDialog::deleteCurrentMacro); + + connect(ui->editMacroName, &QLineEdit::textChanged, this, &MacroEditorDialog::macroNameChanged); + + connect(ui->btnInsertMacroStep, &QPushButton::clicked, this, &MacroEditorDialog::insertMacroStep); + connect(ui->btnDeleteMacroStep, &QPushButton::clicked, this, &MacroEditorDialog::deleteMacroStep); + connect(ui->btnMoveMacroStepUp, &QPushButton::clicked, this, &MacroEditorDialog::moveMacroStepUp); + connect(ui->btnMoveMacroStepDown, &QPushButton::clicked, this, &MacroEditorDialog::moveMacroStepDown); + + QList recordableMacroMessages; + for (Scintilla::Message msg : MacroStep::RecordableMacroMessages()) { + recordableMacroMessages.append(qMakePair(MacroStep::NameOfMessage(msg), static_cast(msg))); + } + ui->tblMacroSteps->setItemDelegateForColumn(0, new ComboBoxDelegate(recordableMacroMessages, this)); + + ui->listMacros->setCurrentIndex(model->index(0)); +} + +MacroEditorDialog::~MacroEditorDialog() +{ + delete ui; +} + +void MacroEditorDialog::rowChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + + if (!current.isValid()){ + ui->editMacroName->setReadOnly(true); + ui->editMacroName->clear(); + ui->keyMacroShortcut->clear(); + if (auto model = ui->tblMacroSteps->model()) { + model->deleteLater(); + } + return; + } + else { + ui->editMacroName->setReadOnly(false); + + Macro *macro = model->macro(current); + + ui->editMacroName->setText(macro->getName()); + + // Replace the existing model + if (auto model = ui->tblMacroSteps->model()) { + model->deleteLater(); + } + ui->tblMacroSteps->setModel(new MacroStepTableModel(macro, this)); + + // Resize some stuff now that we have a new model + ui->tblMacroSteps->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); + ui->tblMacroSteps->resizeRowsToContents(); + ui->tblMacroSteps->resizeColumnToContents(0); + } +} + +void MacroEditorDialog::macroNameChanged(const QString &text) +{ + // Ensure there is a non-blank name + if (text.trimmed().isEmpty()) { + ui->editMacroName->setStyleSheet("QLineEdit{border: 2px solid red}"); + return; + } + else { + ui->editMacroName->setStyleSheet(""); + } + + QModelIndex currentIndex = ui->listMacros->selectionModel()->currentIndex(); + + if (currentIndex.isValid()) { + Macro *macro = model->macro(currentIndex); + macro->setName(text); + + // Since the macro was edited directly, need to notify the model this index changed + emit model->dataChanged(currentIndex, currentIndex); + } +} + +void MacroEditorDialog::deleteCurrentMacro() +{ + QModelIndex currentIndex = ui->listMacros->selectionModel()->currentIndex(); + + if (currentIndex.isValid()) { + const QString macroName = currentIndex.data(Qt::DisplayRole).toString(); + QMessageBox::StandardButton reply = QMessageBox::question(this, tr("Delete Macro"), tr("Are you sure you want to delete %1?").arg(macroName)); + + if (reply == QMessageBox::Yes) { + model->removeRow(currentIndex.row()); + } + } +} + +void MacroEditorDialog::copyCurrentMacro() +{ + QModelIndex currentIndex = ui->listMacros->selectionModel()->currentIndex(); + + if (currentIndex.isValid()) { + Macro *originalMacro = model->macro(currentIndex); + + model->insertRows(currentIndex.row() + 1, 1); + + Macro *newMacro = model->macro(model->index(currentIndex.row() + 1)); + + // TODO: move this into a copy constructor in the Macro class? + + newMacro->setName(originalMacro->getName() + " " + tr("(Copy)")); + + for (const MacroStep &step : qAsConst(originalMacro->getSteps())) { + newMacro->addMacroStep(step); + } + + // Select the newly created macro + ui->listMacros->setCurrentIndex(model->index(currentIndex.row() + 1)); + } +} + +void MacroEditorDialog::insertMacroStep() +{ + QModelIndex currentIndex = ui->tblMacroSteps->selectionModel()->currentIndex(); + + if (currentIndex.isValid()) { + ui->tblMacroSteps->model()->insertRows(currentIndex.row() + 1, 1); + ui->tblMacroSteps->setCurrentIndex(ui->tblMacroSteps->model()->index(currentIndex.row() + 1, 0)); + } + else { + ui->tblMacroSteps->model()->insertRows(0, 1); + ui->tblMacroSteps->setCurrentIndex(ui->tblMacroSteps->model()->index(0, 0)); + } + + // Resize things if needed + ui->tblMacroSteps->resizeRowsToContents(); + ui->tblMacroSteps->resizeColumnToContents(0); +} + +void MacroEditorDialog::deleteMacroStep() +{ + QModelIndex currentIndex = ui->tblMacroSteps->selectionModel()->currentIndex(); + + if (currentIndex.isValid()) { + ui->tblMacroSteps->model()->removeRow(currentIndex.row()); + } +} + +void MacroEditorDialog::moveMacroStepUp() +{ + QModelIndex currentIndex = ui->tblMacroSteps->selectionModel()->currentIndex(); + + if (currentIndex.isValid() && currentIndex.row() != 0) { + // This does not make sense to me, start at the previous index and move it to the next index, but it works + ui->tblMacroSteps->model()->moveRow(QModelIndex(), currentIndex.row() - 1, QModelIndex(), currentIndex.row() + 1); + } +} + +void MacroEditorDialog::moveMacroStepDown() +{ + QModelIndex currentIndex = ui->tblMacroSteps->selectionModel()->currentIndex(); + + if (currentIndex.isValid() && currentIndex.row() != ui->tblMacroSteps->model()->rowCount() - 1) { + // This also does not make ense, start at the current index and skip two + ui->tblMacroSteps->model()->moveRow(QModelIndex(), currentIndex.row(), QModelIndex(), currentIndex.row() + 2); + } +} diff --git a/src/NotepadNext/dialogs/MacroEditorDialog.h b/src/NotepadNext/dialogs/MacroEditorDialog.h new file mode 100644 index 000000000..64aa5e673 --- /dev/null +++ b/src/NotepadNext/dialogs/MacroEditorDialog.h @@ -0,0 +1,59 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MACROEDITORDIALOG_H +#define MACROEDITORDIALOG_H + +#include + +#include "MacroListModel.h" +#include "MacroStepTableModel.h" +#include "MacroManager.h" + +namespace Ui { +class MacroEditorDialog; +} + +class MacroEditorDialog : public QDialog +{ + Q_OBJECT + +public: + explicit MacroEditorDialog(QWidget *parent, MacroManager *mm); + ~MacroEditorDialog(); + +private slots: + void rowChanged(const QModelIndex ¤t, const QModelIndex &previous); + void macroNameChanged(const QString &text); + + void deleteCurrentMacro(); + void copyCurrentMacro(); + + void insertMacroStep(); + void deleteMacroStep(); + void moveMacroStepUp(); + void moveMacroStepDown(); + +private: + Ui::MacroEditorDialog *ui; + MacroManager *macroManager; + MacroListModel *model; +}; + +#endif // MACROEDITORDIALOG_H diff --git a/src/NotepadNext/dialogs/MacroEditorDialog.ui b/src/NotepadNext/dialogs/MacroEditorDialog.ui new file mode 100644 index 000000000..c00f6b367 --- /dev/null +++ b/src/NotepadNext/dialogs/MacroEditorDialog.ui @@ -0,0 +1,265 @@ + + + MacroEditorDialog + + + + 0 + 0 + 606 + 443 + + + + Macro Editor + + + true + + + + + + + + + 200 + 16777215 + + + + QListView::Static + + + true + + + + + + + + + + + + + + Name + + + + + + + + + + Shortcut + + + + + + + + + Steps: + + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::ScrollPerPixel + + + false + + + false + + + false + + + + + + + + + Insert Macro Step + + + + + + + :/icons/table_row_insert.png + + + + + + + + Delete Selected Macro Step + + + + + + + :/icons/table_row_delete.png + + + + + + + + Move Selected Macro Step Up + + + + + + + :/icons/arrow_up.png + + + + + + + + Move Selected Macro Step Down + + + + + + + :/icons/arrow_down.png + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + Copy Selected Macro + + + + + + + :/icons/copy.png + + + + + + + + Delete Selected Macro + + + + + + + :/icons/table_delete.png + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + MacroEditorDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + MacroEditorDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/NotepadNext/dialogs/MacroRunDialog.cpp b/src/NotepadNext/dialogs/MacroRunDialog.cpp new file mode 100644 index 000000000..eb5efc61a --- /dev/null +++ b/src/NotepadNext/dialogs/MacroRunDialog.cpp @@ -0,0 +1,63 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "MacroManager.h" +#include "MacroRunDialog.h" + +#include "ui_MacroRunDialog.h" + + +MacroRunDialog::MacroRunDialog(QWidget *parent, MacroManager *mm) : + QDialog(parent, Qt::Tool), + ui(new Ui::MacroRunDialog), + macroManager(mm) +{ + ui->setupUi(this); + + connect(ui->buttonRun, &QPushButton::clicked, this, [=]() { + Macro *selectedMacro = ui->comboBox->currentData().value(); + int times = -1; // for end of file + + if (ui->radioExecute->isChecked()) { + times = ui->spinTimes->value(); + } + + emit execute(selectedMacro, times); + }); +} + +MacroRunDialog::~MacroRunDialog() +{ + delete ui; +} + +void MacroRunDialog::showEvent(QShowEvent *event) +{ + ui->comboBox->clear(); + + if (macroManager->hasCurrentUnsavedMacro()) { + ui->comboBox->addItem(macroManager->getCurrentMacro()->getName(), QVariant::fromValue(macroManager->getCurrentMacro())); + } + + for (Macro *macro : macroManager->availableMacros()) { + ui->comboBox->addItem(macro->getName(), QVariant::fromValue(macro)); + } + + QDialog::showEvent(event); +} diff --git a/src/NotepadNext/dialogs/MacroRunDialog.h b/src/NotepadNext/dialogs/MacroRunDialog.h new file mode 100644 index 000000000..70384e923 --- /dev/null +++ b/src/NotepadNext/dialogs/MacroRunDialog.h @@ -0,0 +1,52 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MACRORUNDIALOG_H +#define MACRORUNDIALOG_H + + +#include + +class Macro; +class MacroManager; + +namespace Ui { +class MacroRunDialog; +} + +class MacroRunDialog : public QDialog +{ + Q_OBJECT + +public: + MacroRunDialog(QWidget *parent, MacroManager *mm); + ~MacroRunDialog(); + +protected: + void showEvent(QShowEvent *event) override; + +signals: + void execute(Macro *macro, int times); + +private: + Ui::MacroRunDialog *ui; + MacroManager *macroManager; +}; + +#endif // MACRORUNDIALOG_H diff --git a/src/NotepadNext/dialogs/MacroRunDialog.ui b/src/NotepadNext/dialogs/MacroRunDialog.ui new file mode 100644 index 000000000..4cc9513ce --- /dev/null +++ b/src/NotepadNext/dialogs/MacroRunDialog.ui @@ -0,0 +1,232 @@ + + + MacroRunDialog + + + + 0 + 0 + 287 + 170 + + + + Run a Macro Multiple Times + + + + + + 14 + + + + + + 0 + 0 + + + + Macro: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + comboBox + + + + + + + + 0 + 0 + + + + + + + + + + Run Until End of File + + + + + + + Execute... + + + true + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 25 + 20 + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::NoButtons + + + true + + + false + + + 1 + + + 999999999 + + + 10 + + + + + + + times + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Run + + + + + + + Cancel + + + + + + + + + + + radioExecute + toggled(bool) + spinTimes + setEnabled(bool) + + + 210 + 85 + + + 81 + 110 + + + + + radioExecute + toggled(bool) + label_2 + setEnabled(bool) + + + 210 + 85 + + + 139 + 110 + + + + + buttonCancel + clicked() + MacroRunDialog + close() + + + 251 + 169 + + + 210 + 95 + + + + + diff --git a/src/NotepadNext/dialogs/MacroSaveDialog.cpp b/src/NotepadNext/dialogs/MacroSaveDialog.cpp new file mode 100644 index 000000000..b367f92d5 --- /dev/null +++ b/src/NotepadNext/dialogs/MacroSaveDialog.cpp @@ -0,0 +1,49 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "MacroSaveDialog.h" +#include "ui_MacroSaveDialog.h" + +MacroSaveDialog::MacroSaveDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::MacroSaveDialog) +{ + setWindowFlag(Qt::WindowContextHelpButtonHint, false); + + ui->setupUi(this); + + connect(ui->editName, &QLineEdit::textChanged, [=](const QString &text) { + ui->buttonOk->setEnabled(text.trimmed().size() > 0); + }); +} + +MacroSaveDialog::~MacroSaveDialog() +{ + delete ui; +} + +QString MacroSaveDialog::getName() const +{ + return ui->editName->text(); +} + +QKeySequence MacroSaveDialog::getShortcut() const +{ + return ui->keySequenceEdit->keySequence(); +} diff --git a/src/NotepadNext/dialogs/MacroSaveDialog.h b/src/NotepadNext/dialogs/MacroSaveDialog.h new file mode 100644 index 000000000..566e67d6e --- /dev/null +++ b/src/NotepadNext/dialogs/MacroSaveDialog.h @@ -0,0 +1,44 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MACROSAVEDIALOG_H +#define MACROSAVEDIALOG_H + +#include + +namespace Ui { +class MacroSaveDialog; +} + +class MacroSaveDialog : public QDialog +{ + Q_OBJECT + +public: + explicit MacroSaveDialog(QWidget *parent = 0); + ~MacroSaveDialog(); + + QString getName() const; + QKeySequence getShortcut() const; + +private: + Ui::MacroSaveDialog *ui; +}; + +#endif // MACROSAVEDIALOG_H diff --git a/src/NotepadNext/dialogs/MacroSaveDialog.ui b/src/NotepadNext/dialogs/MacroSaveDialog.ui new file mode 100644 index 000000000..00b4558f3 --- /dev/null +++ b/src/NotepadNext/dialogs/MacroSaveDialog.ui @@ -0,0 +1,132 @@ + + + MacroSaveDialog + + + + 0 + 0 + 342 + 116 + + + + Save Macro + + + true + + + + + + + + Name: + + + + + + + 256 + + + + + + + Shortcut: + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + OK + + + + + + + Cancel + + + + + + + + + + + buttonOk + clicked() + MacroSaveDialog + accept() + + + 122 + 108 + + + 162 + 64 + + + + + buttonCancel + clicked() + MacroSaveDialog + reject() + + + 203 + 108 + + + 162 + 64 + + + + + diff --git a/src/NotepadNext/dialogs/MainWindow.cpp b/src/NotepadNext/dialogs/MainWindow.cpp new file mode 100644 index 000000000..bfce3586a --- /dev/null +++ b/src/NotepadNext/dialogs/MainWindow.cpp @@ -0,0 +1,2141 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "MainWindow.h" +#include "BookMarkDecorator.h" +#include "URLFinder.h" +#include "SessionManager.h" +#include "UndoAction.h" +#include "ui_MainWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef Q_OS_WIN +#include +#include +#endif + +#include "DockAreaWidget.h" + +#include "NotepadNextApplication.h" +#include "ApplicationSettings.h" + +#include "ScintillaNext.h" + +#include "RecentFilesListManager.h" +#include "RecentFilesListMenuBuilder.h" +#include "EditorManager.h" + +#include "LuaConsoleDock.h" +#include "LanguageInspectorDock.h" +#include "EditorInspectorDock.h" +#include "FolderAsWorkspaceDock.h" +#include "SearchResultsDock.h" +#include "DebugLogDock.h" +#include "HexViewerDock.h" +#include "FileListDock.h" + +#include "FindReplaceDialog.h" +#include "MacroRunDialog.h" +#include "MacroSaveDialog.h" +#include "PreferencesDialog.h" +#include "ColumnEditorDialog.h" + +#include "QuickFindWidget.h" + +#include "EditorPrintPreviewRenderer.h" +#include "MacroEditorDialog.h" + +#include "ZoomEventWatcher.h" +#include "FileDialogHelpers.h" + +#include "HtmlConverter.h" +#include "RtfConverter.h" + +#include "FadingIndicator.h" + +#include "ThemeColors.h" + +QString loadCssFile(const QString& cssFile) +{ + QFile f(cssFile); + if (!f.exists()) { + qInfo("Stylesheet resource file '%s' not found, no style sheet set", qUtf8Printable(cssFile)); + + return ""; + } + else { + qInfo("Stylesheet resource file '%s' loaded", qUtf8Printable(cssFile)); + + f.open(QFile::ReadOnly); + QTextStream ts(&f); + QString cssContent = ts.readAll(); + f.close(); + + return cssContent; + } +} + +MainWindow::MainWindow(NotepadNextApplication *app) : + ui(new Ui::MainWindow), + app(app), + zoomEventWatcher(new ZoomEventWatcher(this)) +{ + qInfo(Q_FUNC_INFO); + + setAttribute(Qt::WA_DeleteOnClose); + + ui->setupUi(this); + + applyCustomShortcuts(); + + qInfo("setupUi Completed"); + + connect(this, &MainWindow::aboutToClose, this, &MainWindow::saveSettings); + + // Create and set up the connections to the docked editor + dockedEditor = new DockedEditor(this); + connect(dockedEditor, &DockedEditor::editorCloseRequested, this, [=](ScintillaNext *editor) { closeFile(editor); }); + connect(dockedEditor, &DockedEditor::editorActivated, this, &MainWindow::activateEditor); + connect(dockedEditor, &DockedEditor::contextMenuRequestedForEditor, this, &MainWindow::tabBarRightClicked); + connect(dockedEditor, &DockedEditor::titleBarDoubleClicked, this, &MainWindow::newFile); + + // Set up the menus + connect(ui->actionNew, &QAction::triggered, this, &MainWindow::newFile); + connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openFileDialog); + connect(ui->actionReload, &QAction::triggered, this, &MainWindow::reloadFile); + connect(ui->actionClose, &QAction::triggered, this, &MainWindow::closeCurrentFile); + connect(ui->actionCloseAll, &QAction::triggered, this, &MainWindow::closeAllFiles); + connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); + +#ifdef Q_OS_WIN + ui->actionExit->setShortcut(QKeySequence("Alt+F4")); +#else + ui->actionExit->setShortcut(QKeySequence::Quit); +#endif + + connect(ui->actionOpenFolderasWorkspace, &QAction::triggered, this, &MainWindow::openFolderAsWorkspaceDialog); + + connect(ui->actionCloseAllExceptActive, &QAction::triggered, this, &MainWindow::closeAllExceptActive); + connect(ui->actionCloseAllToLeft, &QAction::triggered, this, &MainWindow::closeAllToLeft); + connect(ui->actionCloseAllToRight, &QAction::triggered, this, &MainWindow::closeAllToRight); + + connect(ui->actionSave, &QAction::triggered, this, &MainWindow::saveCurrentFile); + connect(ui->actionSaveAs, &QAction::triggered, this, &MainWindow::saveCurrentFileAsDialog); + connect(ui->actionSaveCopyAs, &QAction::triggered, this, &MainWindow::saveCopyAsDialog); + connect(ui->actionSaveAll, &QAction::triggered, this, &MainWindow::saveAll); + connect(ui->actionRename, &QAction::triggered, this, &MainWindow::renameFile); + + connect(ui->actionExportHtml, &QAction::triggered, this, [=]() { + HtmlConverter html(currentEditor()); + exportAsFormat(&html, QStringLiteral("HTML files (*.html)")); + }); + + connect(ui->actionExportRtf, &QAction::triggered, this, [=]() { + RtfConverter rtf(currentEditor()); + exportAsFormat(&rtf, QStringLiteral("RTF Files (*.rtf)")); + }); + + connect(ui->actionPrint, &QAction::triggered, this, &MainWindow::print); + + connect(ui->actionToggleSingleLineComment, &QAction::triggered, this, [=]() { currentEditor()->toggleCommentSelection(); }); + connect(ui->actionSingleLineComment, &QAction::triggered, this, [=]() { currentEditor()->commentLineSelection(); }); + connect(ui->actionSingleLineUncomment, &QAction::triggered, this, [=]() { currentEditor()->uncommentLineSelection(); }); + + connect(ui->actionBase64Encode,&QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + const QByteArray selection = currentEditor()->getSelText(); + editor->replaceSel(selection.toBase64().constData()); + }); + connect(ui->actionURLEncode,&QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + const QByteArray selection = currentEditor()->getSelText(); + editor->replaceSel(selection.toPercentEncoding().constData()); + }); + connect(ui->actionBase64Decode,&QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + const QByteArray selection = editor->getSelText(); + if (auto result = QByteArray::fromBase64Encoding(selection)) { + editor->replaceSel((*result).constData()); + } + }); + connect(ui->actionURLDecode,&QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + const QByteArray selection = editor->getSelText(); + editor->replaceSel(QByteArray::fromPercentEncoding(selection).constData()); + }); + connect(ui->actionCopyURL, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + URLFinder *urlFinder = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + if (urlFinder && urlFinder->isEnabled()) { + urlFinder->copyURLToClipboard(contextMenuPos); + } + }); + + connect(ui->actionClearRecentFilesList, &QAction::triggered, app->getRecentFilesListManager(), &RecentFilesListManager::clear); + + connect(ui->actionMoveToTrash, &QAction::triggered, this, &MainWindow::moveCurrentFileToTrash); + + RecentFilesListMenuBuilder *recentFileListMenuBuilder = new RecentFilesListMenuBuilder(app->getRecentFilesListManager()); + connect(ui->menuRecentFiles, &QMenu::aboutToShow, this, [=]() { + // NOTE: its unfortunate that this has to be hard coded, but there's no way + // to easily determine what should or shouldn't be there + while (ui->menuRecentFiles->actions().size() > 4) { + delete ui->menuRecentFiles->actions().takeLast(); + } + + recentFileListMenuBuilder->populateMenu(ui->menuRecentFiles); + }); + + connect(ui->actionRestoreRecentlyClosedFile, &QAction::triggered, this, [=]() { + if (app->getRecentFilesListManager()->count() > 0) { + openFileList(QStringList() << app->getRecentFilesListManager()->mostRecentFile()); + } + }); + + connect(ui->actionOpenAllRecentFiles, &QAction::triggered, this, [=]() { + openFileList(app->getRecentFilesListManager()->fileList()); + }); + + connect(recentFileListMenuBuilder, &RecentFilesListMenuBuilder::fileOpenRequest, this, &MainWindow::openFile); + + QActionGroup *eolActionGroup = new QActionGroup(this); + eolActionGroup->addAction(ui->actionWindows); + eolActionGroup->addAction(ui->actionUnix); + eolActionGroup->addAction(ui->actionMacintosh); + + connect(ui->actionWindows, &QAction::triggered, this, [=]() { convertEOLs(SC_EOL_CRLF); }); + connect(ui->actionUnix, &QAction::triggered, this, [=]() { convertEOLs(SC_EOL_LF); }); + connect(ui->actionMacintosh, &QAction::triggered, this, [=]() { convertEOLs(SC_EOL_CR); }); + + connect(ui->actionUpperCase, &QAction::triggered, this, [=]() { currentEditor()->upperCase(); }); + connect(ui->actionLowerCase, &QAction::triggered, this, [=]() { currentEditor()->lowerCase(); }); + + connect(ui->actionDuplicateCurrentLine, &QAction::triggered, this, [=]() { currentEditor()->lineDuplicate(); }); + connect(ui->actionMoveSelectedLinesUp, &QAction::triggered, this, [=]() { currentEditor()->moveSelectedLinesUp(); }); + connect(ui->actionMoveSelectedLinesDown, &QAction::triggered, this, [=]() { currentEditor()->moveSelectedLinesDown(); }); + connect(ui->actionSplitLines, &QAction::triggered, this, [=]() { + currentEditor()->targetFromSelection(); + currentEditor()->linesSplit(0); + }); + connect(ui->actionJoinLines, &QAction::triggered, this, [=]() { + currentEditor()->targetFromSelection(); + currentEditor()->linesJoin(); + }); + connect(ui->actionRemoveEmptyLines, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + Finder f(editor); + const UndoAction ua(editor); + + f.setSearchText(QStringLiteral("\\R\\R+")); + f.setSearchFlags(SCFIND_REGEXP); + f.replaceAll(editor->eolString()); + + // The regex will not entirely remove a blank first line + editor->deleteLeadingEmptyLines(); + + // Regex will also not delete the final blank line + editor->deleteTrailingEmptyLines(); + }); + + connect(ui->actionColumnMode, &QAction::triggered, this, [=]() { + ColumnEditorDialog *columnEditor = findChild(QString(), Qt::FindDirectChildrenOnly); + + if (columnEditor == Q_NULLPTR) { + columnEditor = new ColumnEditorDialog(this); + } + + columnEditor->show(); + columnEditor->raise(); + columnEditor->activateWindow(); + }); + + connect(ui->actionUndo, &QAction::triggered, this, [=]() { currentEditor()->undo(); }); + connect(ui->actionRedo, &QAction::triggered, this, [=]() { currentEditor()->redo(); }); + connect(ui->actionCut, &QAction::triggered, this, [=]() { currentEditor()->cutAllowLine(); }); + connect(ui->actionCopy, &QAction::triggered, this, [=]() { currentEditor()->copyAllowLine(); }); + connect(ui->actionDelete, &QAction::triggered, this, [=]() { currentEditor()->clear(); }); + connect(ui->actionPaste, &QAction::triggered, this, [=]() { currentEditor()->paste(); }); + connect(ui->actionSelectAll, &QAction::triggered, this, [=]() { currentEditor()->selectAll(); }); + connect(ui->actionSelectNext, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + + editor->setSearchFlags(SCFIND_NONE); + editor->targetWholeDocument(); + editor->multipleSelectAddNext(); + }); + connect(ui->actionCopyFullPath, &QAction::triggered, this, [=]() { + auto editor = currentEditor(); + if (editor->isFile()) { + QApplication::clipboard()->setText(editor->getFilePath()); + } + }); + connect(ui->actionCopyFileName, &QAction::triggered, this, [=]() { + QApplication::clipboard()->setText(currentEditor()->getName()); + }); + connect(ui->actionCopyFileDirectory, &QAction::triggered, this, [=]() { + auto editor = currentEditor(); + if (editor->isFile()) { + QApplication::clipboard()->setText(editor->getPath()); + } + }); + + connect(ui->actionCopyAsHtml, &QAction::triggered, this, [=]() { + HtmlConverter html(currentEditor()); + copyAsFormat(&html, "text/html"); + }); + + connect(ui->actionCopyAsRtf, &QAction::triggered, this, [=]() { + RtfConverter rtf(currentEditor()); + copyAsFormat(&rtf, "Rich Text Format"); + }); + + connect(ui->actionIncrease_Indent, &QAction::triggered, this, [=]() { currentEditor()->tab(); }); + connect(ui->actionDecrease_Indent, &QAction::triggered, this, [=]() { currentEditor()->backTab(); }); + + addAction(ui->actionToggleOverType); + connect(ui->actionToggleOverType, &QAction::triggered, this, [=]() { + currentEditor()->editToggleOvertype(); + ui->statusBar->refresh(currentEditor()); + }); + + SearchResultsDock *srDock = new SearchResultsDock(this); + addDockWidget(Qt::BottomDockWidgetArea, srDock); + srDock->toggleViewAction()->setShortcut(Qt::Key_F7); + ui->menuView->addAction(srDock->toggleViewAction()); + + connect(srDock, &SearchResultsDock::searchResultActivated, this, [=](ScintillaNext *editor, int lineNumber, int startPositionFromBeginning, int endPositionFromBeginning) { + dockedEditor->switchToEditor(editor); + + int linePos = editor->positionFromLine(lineNumber); + editor->goToRange({linePos + startPositionFromBeginning, linePos + endPositionFromBeginning}); + editor->verticalCentreCaret(); + + editor->grabFocus(); + }); + + connect(ui->actionFind, &QAction::triggered, this, [=]() { + showFindReplaceDialog(FindReplaceDialog::FIND_TAB); + }); + + connect(ui->actionFindNext, &QAction::triggered, this, [=]() { + FindReplaceDialog *f = findChild(QString(), Qt::FindDirectChildrenOnly); + + if (f) { + f->performLastSearch(); + } + }); + + connect(ui->actionQuickFind, &QAction::triggered, this, [=]() { + QuickFindWidget *quickFind = findChild(QString(), Qt::FindDirectChildrenOnly); + + if (quickFind == Q_NULLPTR) { + quickFind = new QuickFindWidget(this); + } + + quickFind->setEditor(currentEditor()); + quickFind->setFocus(); + quickFind->show(); + }); + + connect(ui->actionReplace, &QAction::triggered, this, [=]() { + showFindReplaceDialog(FindReplaceDialog::REPLACE_TAB); + }); + + connect(ui->actionGoToLine, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + const int currentLine = editor->lineFromPosition(editor->currentPos()) + 1; + const int maxLine = editor->lineCount(); + bool ok; + + QInputDialog d = QInputDialog(this); + Qt::WindowFlags flags = d.windowFlags() & ~Qt::WindowContextHelpButtonHint; + int lineToGoTo = d.getInt(this, tr("Go to line"), tr("Line Number (1 - %1)").arg(maxLine), currentLine, 1, maxLine, 1, &ok, flags); + + if (ok) { + editor->ensureVisible(lineToGoTo - 1); + editor->gotoLine(lineToGoTo - 1); + editor->verticalCentreCaret(); + } + }); + + connect(ui->actionToggleBookmark, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + BookMarkDecorator *bookMarkDecorator = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + + if (bookMarkDecorator && bookMarkDecorator->isEnabled()) { + editor->forEachLineInSelection(editor->mainSelection(), [&](int line) { + bookMarkDecorator->toggleBookmark(line); + }); + } + }); + + connect(ui->actionNextBookmark, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + BookMarkDecorator *bookMarkDecorator = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + + if (bookMarkDecorator && bookMarkDecorator->isEnabled()) { + int currentLine = editor->lineFromPosition(editor->currentPos()); + int nextBookmarkedLine = bookMarkDecorator->nextBookmarkAfter(currentLine + 1); + + if (nextBookmarkedLine != -1) { + editor->ensureVisibleEnforcePolicy(nextBookmarkedLine); + editor->gotoLine(nextBookmarkedLine); + } + } + }); + + connect(ui->actionClearBookmarks, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + BookMarkDecorator *bookMarkDecorator = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + + if (bookMarkDecorator && bookMarkDecorator->isEnabled()) { + bookMarkDecorator->clearBookmarks(); + } + }); + + connect(ui->actionInvertBookmarks, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + BookMarkDecorator *bookMarkDecorator = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + + if (bookMarkDecorator && bookMarkDecorator->isEnabled()) { + for (int line = 0; line < editor->lineCount(); line++) { + bookMarkDecorator->toggleBookmark(line); + } + } + }); + + connect(ui->actionPreviousBookmark, &QAction::triggered, this, [=]() { + ScintillaNext *editor = currentEditor(); + BookMarkDecorator *bookMarkDecorator = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + + if (bookMarkDecorator && bookMarkDecorator->isEnabled()) { + int currentLine = editor->lineFromPosition(editor->currentPos()); + int prevBookmarkedLine = bookMarkDecorator->previousBookMarkBefore(currentLine - 1); + + if (prevBookmarkedLine != -1) { + editor->ensureVisibleEnforcePolicy(prevBookmarkedLine); + editor->gotoLine(prevBookmarkedLine); + } + } + }); + + // The action needs added to the window so it can be triggered via the keyboard + addAction(ui->actionNextTab); + connect(ui->actionNextTab, &QAction::triggered, this, [=]() { + int index = dockedEditor->currentDockArea()->currentIndex(); + int total = dockedEditor->currentDockArea()->dockWidgetsCount(); + + index++; + dockedEditor->currentDockArea()->setCurrentIndex(index < total ? index : 0); + }); + + // The action needs added to the window so it can be triggered via the keyboard + addAction(ui->actionPreviousTab); + connect(ui->actionPreviousTab, &QAction::triggered, this, [=]() { + int index = dockedEditor->currentDockArea()->currentIndex(); + int total = dockedEditor->currentDockArea()->dockWidgetsCount(); + + index--; + dockedEditor->currentDockArea()->setCurrentIndex(index >= 0 ? index : total - 1); + }); + + ui->pushExitFullScreen->setParent(this); // This is important + ui->pushExitFullScreen->setVisible(false); + connect(ui->pushExitFullScreen, &QPushButton::clicked, ui->actionFullScreen, &QAction::trigger); + connect(ui->actionFullScreen, &QAction::triggered, this, [=](bool b) { + static bool wasMaximized; + + if (b) { + // NOTE: don't hide() these as it will cancel their actions they hold + ui->menuBar->setMaximumHeight(0); + ui->mainToolBar->setMaximumHeight(0); + + wasMaximized = isMaximized(); + if (wasMaximized) { + // By default when calling showMaximized() from a full screen state, the window will resize + // to its "normal" size and then immediately resize to the "maximized" size which is very ugly. + // By calling setGeometry() to the size of the screen, it at least alleviates the ugly animation + // going from: fullscreen -> small "normal" size -> full size of screen + setGeometry(screen()->availableGeometry()); + } + + showFullScreen(); + + ui->pushExitFullScreen->setGeometry(width() - 20, 0, 20, 20); + ui->pushExitFullScreen->show(); + ui->pushExitFullScreen->raise(); + } + else { + ui->menuBar->setMaximumHeight(QWIDGETSIZE_MAX); + ui->mainToolBar->setMaximumHeight(QWIDGETSIZE_MAX); + + if (wasMaximized) + showMaximized(); + else + showNormal(); + + ui->pushExitFullScreen->hide(); + } + }); + + + // Show All Characters is just a short cut to toggle whitespace and EOL on + ui->actionShowAllCharacters->setChecked(app->getSettings()->showWhitespace() && app->getSettings()->showEndOfLine()); + connect(ui->actionShowAllCharacters, &QAction::triggered, app->getSettings(), &ApplicationSettings::setShowWhitespace); + connect(ui->actionShowAllCharacters, &QAction::triggered, app->getSettings(), &ApplicationSettings::setShowEndOfLine); + + // Show White Space + ui->actionShowWhitespace->setChecked(app->getSettings()->showWhitespace()); + connect(app->getSettings(), &ApplicationSettings::showWhitespaceChanged, ui->actionShowWhitespace, &QAction::setChecked); + connect(ui->actionShowWhitespace, &QAction::toggled, app->getSettings(), &ApplicationSettings::setShowWhitespace); + // Update the "Show All Character" action + connect(ui->actionShowWhitespace, &QAction::toggled, this, [=](bool b) { + ui->actionShowAllCharacters->setChecked(b && ui->actionShowEndofLine->isChecked()); + }); + + // Show EOL + ui->actionShowEndofLine->setChecked(app->getSettings()->showEndOfLine()); + connect(app->getSettings(), &ApplicationSettings::showEndOfLineChanged, ui->actionShowEndofLine, &QAction::setChecked); + connect(ui->actionShowEndofLine, &QAction::toggled, app->getSettings(), &ApplicationSettings::setShowEndOfLine); + // Update the "Show All Character" action + connect(ui->actionShowEndofLine, &QAction::toggled, this, [=](bool b) { + ui->actionShowAllCharacters->setChecked(b && ui->actionShowWhitespace->isChecked()); + }); + + // Show Wrap Symbol + ui->actionShowWrapSymbol->setChecked(app->getSettings()->showWrapSymbol()); + connect(app->getSettings(), &ApplicationSettings::showWrapSymbolChanged, ui->actionShowWrapSymbol, &QAction::setChecked); + connect(ui->actionShowWrapSymbol, &QAction::toggled, app->getSettings(), &ApplicationSettings::setShowWrapSymbol); + + // Show Indentation Guide + ui->actionShowIndentGuide->setChecked(app->getSettings()->showIndentGuide()); + connect(app->getSettings(), &ApplicationSettings::showIndentGuideChanged, ui->actionShowIndentGuide, &QAction::setChecked); + connect(ui->actionShowIndentGuide, &QAction::toggled, app->getSettings(), &ApplicationSettings::setShowIndentGuide); + + // Word Wrap + ui->actionWordWrap->setChecked(app->getSettings()->wordWrap()); + connect(app->getSettings(), &ApplicationSettings::wordWrapChanged, ui->actionWordWrap, &QAction::setChecked); + connect(ui->actionWordWrap, &QAction::toggled, app->getSettings(), &ApplicationSettings::setWordWrap); + + // Zooming controls all editors simulaneously + connect(ui->actionZoomIn, &QAction::triggered, this, [=]() { + for (ScintillaNext *editor : editors()) { + editor->zoomIn(); + } + zoomLevel = currentEditor()->zoom(); + + showEditorZoomLevelIndicator(); + }); + connect(ui->actionZoomOut, &QAction::triggered, this, [=]() { + for (ScintillaNext *editor : editors()) { + editor->zoomOut(); + } + zoomLevel = currentEditor()->zoom(); + + showEditorZoomLevelIndicator(); + }); + connect(ui->actionZoomReset, &QAction::triggered, this, [=]() { + for (ScintillaNext *editor : editors()) { + editor->setZoom(0); + } + zoomLevel = 0; + + showEditorZoomLevelIndicator(); + }); + + // Zoom watcher has detected a zoom event, so just trigger the UI action + connect(zoomEventWatcher, &ZoomEventWatcher::zoomIn, ui->actionZoomIn, &QAction::trigger); + connect(zoomEventWatcher, &ZoomEventWatcher::zoomOut, ui->actionZoomOut, &QAction::trigger); + + connect(ui->actionFoldAll, &QAction::triggered, this, [=]() { currentEditor()->foldAll(SC_FOLDACTION_CONTRACT | SC_FOLDACTION_CONTRACT_EVERY_LEVEL); }); + connect(ui->actionUnfoldAll, &QAction::triggered, this, [=]() { currentEditor()->foldAll(SC_FOLDACTION_EXPAND | SC_FOLDACTION_CONTRACT_EVERY_LEVEL); }); + + connect(ui->actionFoldLevel1, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(0); }); + connect(ui->actionFoldLevel2, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(1); }); + connect(ui->actionFoldLevel3, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(2); }); + connect(ui->actionFoldLevel4, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(3); }); + connect(ui->actionFoldLevel5, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(4); }); + connect(ui->actionFoldLevel6, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(5); }); + connect(ui->actionFoldLevel7, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(6); }); + connect(ui->actionFoldLevel8, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(7); }); + connect(ui->actionFoldLevel9, &QAction::triggered, this, [=]() { currentEditor()->foldAllLevels(8); }); + + connect(ui->actionUnfoldLevel1, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(0); }); + connect(ui->actionUnfoldLevel2, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(1); }); + connect(ui->actionUnfoldLevel3, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(2); }); + connect(ui->actionUnfoldLevel4, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(3); }); + connect(ui->actionUnfoldLevel5, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(4); }); + connect(ui->actionUnfoldLevel6, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(5); }); + connect(ui->actionUnfoldLevel7, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(6); }); + connect(ui->actionUnfoldLevel8, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(7); }); + connect(ui->actionUnfoldLevel9, &QAction::triggered, this, [=]() { currentEditor()->unFoldAllLevels(8); }); + + languageActionGroup = new QActionGroup(this); + languageActionGroup->setExclusive(true); + + connect(ui->actionPreferences, &QAction::triggered, this, [=] { + PreferencesDialog *pd = findChild(QString(), Qt::FindDirectChildrenOnly); + + if (pd == Q_NULLPTR) { + pd = new PreferencesDialog(app->getSettings(), this); + } + + pd->show(); + pd->raise(); + pd->activateWindow(); + }); + + // The macro manager has already loaded any saved macros, so it might have some already + ui->actionRunMacroMultipleTimes->setEnabled(macroManager.availableMacros().size() > 0); + ui->actionEditMacros->setEnabled(macroManager.availableMacros().size() > 0); + + connect(ui->actionMacroRecording, &QAction::triggered, this, [=](bool b) { + if (b) { + macroManager.startRecording(currentEditor()); + } + else { + macroManager.stopRecording(); + } + }); + + connect(¯oManager, &MacroManager::recordingStarted, this, [=]() { + ui->actionMacroRecording->setText(tr("Stop Recording")); + + // A macro is being recorded so disable some macro options + ui->actionPlayback->setEnabled(false); + ui->actionRunMacroMultipleTimes->setEnabled(false); + ui->actionSaveCurrentRecordedMacro->setEnabled(false); + }); + + connect(¯oManager, &MacroManager::recordingStopped, this, [=]() { + ui->actionMacroRecording->setText(tr("Start Recording")); + + // Only enable these if the macro manager recorded a valid macro + ui->actionPlayback->setEnabled(macroManager.hasCurrentUnsavedMacro()); + ui->actionSaveCurrentRecordedMacro->setEnabled(macroManager.hasCurrentUnsavedMacro()); + + // The macro manager might have other macros + ui->actionRunMacroMultipleTimes->setEnabled(macroManager.availableMacros().size() > 0 || macroManager.hasCurrentUnsavedMacro()); + }); + + connect(ui->actionPlayback, &QAction::triggered, this, [=]() { + macroManager.replayCurrentMacro(currentEditor()); + }); + + connect(ui->actionSaveCurrentRecordedMacro, &QAction::triggered, this, [=]() { + MacroSaveDialog macroSaveDialog; + + macroSaveDialog.show(); + macroSaveDialog.raise(); + macroSaveDialog.activateWindow(); + + if (macroSaveDialog.exec() == QDialog::Accepted) { + // We have at least 1 saved macro at this point + ui->actionEditMacros->setEnabled(true); + + // The macro has been saved so disable save option + ui->actionSaveCurrentRecordedMacro->setEnabled(false); + + // TODO: does the macro name already exist? Make the user retry + + macroManager.saveCurrentMacro(macroSaveDialog.getName()); + + // TODO handle shortcuts + if (!macroSaveDialog.getShortcut().isEmpty()) { + // do something with msd.getShortcut().isEmpty() + } + } + }); + + connect(ui->actionRunMacroMultipleTimes, &QAction::triggered, this, [=]() { + MacroRunDialog *macroRunDialog = findChild(QString(), Qt::FindDirectChildrenOnly); + + if (macroRunDialog == Q_NULLPTR) { + macroRunDialog = new MacroRunDialog(this, ¯oManager); + + connect(macroRunDialog, &MacroRunDialog::execute, this, [=](Macro *macro, int times) { + if (times > 0) + macro->replay(currentEditor(), times); + else if (times == -1) + macro->replayTillEndOfFile(currentEditor()); + }); + } + + macroRunDialog->show(); + macroRunDialog->raise(); + macroRunDialog->activateWindow(); + }); + + connect(ui->actionEditMacros, &QAction::triggered, this, [=]() { + MacroEditorDialog med(this, ¯oManager); + + med.show(); + med.raise(); + med.activateWindow(); + + med.exec(); + + ui->actionEditMacros->setEnabled(macroManager.availableMacros().size() > 0); + }); + + connect(ui->menuMacro, &QMenu::aboutToShow, this, [=]() { + // NOTE: its unfortunate that this has to be hard coded, but there's no way + // to easily determine what should or shouldn't be there + while (ui->menuMacro->actions().size() > 6) { + delete ui->menuMacro->actions().takeLast(); + } + + for (const Macro *m : macroManager.availableMacros()) { + ui->menuMacro->addAction(m->getName(), [=]() { m->replay(currentEditor()); }); + } + }); + + ui->actionAboutQt->setIcon(QPixmap(QLatin1String(":/qt-project.org/qmessagebox/images/qtlogo-64.png"))); + connect(ui->actionAboutQt, &QAction::triggered, &QApplication::aboutQt); + + ui->actionAboutNotepadNext->setShortcut(QKeySequence::HelpContents); + connect(ui->actionAboutNotepadNext, &QAction::triggered, this, [=]() { + QMessageBox::about(this, QString(), + QStringLiteral("

%1 v%2%3

" + "

%4

" + "

This program does stuff.

" + R"(

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, either version 3 of the License, or + (at your option) any later version.

+

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.

+

You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>.

)") + .arg(QApplication::applicationDisplayName(), APP_VERSION, APP_DISTRIBUTION, QStringLiteral(APP_COPYRIGHT).toHtmlEscaped())); + }); + +#ifdef Q_OS_WIN + connect(ui->actionShowInExplorer, &QAction::triggered, this, [=]() { + QStringList arguments; + arguments << "/select," << QDir::toNativeSeparators(currentEditor()->getFileInfo().canonicalFilePath()); + QProcess::startDetached("explorer", arguments); + }); + connect(ui->actionOpenCommandPromptHere, &QAction::triggered, this, [=]() { + QStringList arguments; + arguments << "/c" << "start" << "/d" << QDir::toNativeSeparators(currentEditor()->getFileInfo().dir().canonicalPath()) << "cmd"; + QProcess::startDetached(QStringLiteral("cmd"), arguments); + }); +#endif + + EditorInspectorDock *editorInspectorDock = new EditorInspectorDock(this); + editorInspectorDock->hide(); + addDockWidget(Qt::RightDockWidgetArea, editorInspectorDock); + + LanguageInspectorDock *languageInspectorDock = new LanguageInspectorDock(this); + languageInspectorDock->hide(); + addDockWidget(Qt::RightDockWidgetArea, languageInspectorDock); + + LuaConsoleDock *luaConsoleDock = new LuaConsoleDock(app->getLuaState(), this); + luaConsoleDock->hide(); + addDockWidget(Qt::BottomDockWidgetArea, luaConsoleDock); + + DebugLogDock *debugLogDock = new DebugLogDock(this); + debugLogDock->hide(); + addDockWidget(Qt::RightDockWidgetArea, debugLogDock); + + HexViewerDock *hexViewerDock = new HexViewerDock(this); + hexViewerDock->hide(); + addDockWidget(Qt::RightDockWidgetArea, hexViewerDock); + + ui->menuHelp->insertActions(ui->menuHelp->actions().at(0), { + luaConsoleDock->toggleViewAction(), + languageInspectorDock->toggleViewAction(), + editorInspectorDock->toggleViewAction(), + debugLogDock->toggleViewAction(), + hexViewerDock->toggleViewAction() + }); + + FolderAsWorkspaceDock *fawDock = new FolderAsWorkspaceDock(this); + fawDock->hide(); + addDockWidget(Qt::LeftDockWidgetArea, fawDock); + ui->menuView->addAction(fawDock->toggleViewAction()); + connect(fawDock, &FolderAsWorkspaceDock::fileDoubleClicked, this, &MainWindow::openFile); + + FileListDock *fileListDock = new FileListDock(this); + fileListDock->hide(); + addDockWidget(Qt::LeftDockWidgetArea, fileListDock); + ui->menuView->addAction(fileListDock->toggleViewAction()); + + connect(app->getSettings(), &ApplicationSettings::showMenuBarChanged, this, [=](bool showMenuBar) { + // Don't 'hide' it, else the actions won't be enabled + ui->menuBar->setMaximumHeight(showMenuBar ? QWIDGETSIZE_MAX : 0); + }); + connect(app->getSettings(), &ApplicationSettings::showToolBarChanged, ui->mainToolBar, &QToolBar::setVisible); + connect(app->getSettings(), &ApplicationSettings::showStatusBarChanged, ui->statusBar, &QStatusBar::setVisible); + + // It seems restoreState() does not affect the status bar so set it manually + ui->statusBar->setVisible(app->getSettings()->showStatusBar()); + + setupLanguageMenu(); + + applyStyleSheet(); + + restoreSettings(); + + initUpdateCheck(); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::applyCustomShortcuts() +{ + ApplicationSettings *settings = app->getSettings(); + + settings->beginGroup("Shortcuts"); + + for (const QString &actionName : settings->childKeys()) { + QAction *action = findChild(QStringLiteral("action") + actionName, Qt::FindDirectChildrenOnly); + const QString shortcutString = settings->value(actionName).toString(); + + if (action != Q_NULLPTR) { + action->setShortcut(QKeySequence(shortcutString)); + } + else { + qWarning() << "Cannot find action" << actionName; + } + } + + settings->endGroup(); +} + +void MainWindow::setupLanguageMenu() +{ + qInfo(Q_FUNC_INFO); + + QStringList language_names = app->getLanguages(); + + QString subMenuStyleSheet; // sub menu style sheet, for dark mode only + bool darkMode = app->getSettings()->darkMode(); + if (darkMode) { + subMenuStyleSheet = QString("color:#%1; background-color:#%2") + .arg(DARK_MENU_COLOR, 0, 16) + .arg(DARK_MENU_BG_COLOR, 0, 16); + } + + int i = 0; + while (i < language_names.size()) { + QList actions; + int j = i; + + // Get all consecutive names that start with the same letter + // NOTE: this loop always runs once since i == j the first time + while (j < language_names.size() && language_names[i][0].toUpper() == language_names[j][0].toUpper()) { + const QString key = language_names[j]; + QAction *action = new QAction(key); + action->setCheckable(true); + action->setData(key); + connect(action, &QAction::triggered, this, &MainWindow::languageMenuTriggered); + languageActionGroup->addAction(action); + actions.append(action); + + ++j; + } + + if (actions.size() == 1) { + ui->menuLanguage->addActions(actions); + } + else { + // Create a sub menu with the actions + QMenu *compactMenu = new QMenu(actions[0]->text().at(0).toUpper()); + compactMenu->addActions(actions); + ui->menuLanguage->addMenu(compactMenu); + + // Set background color of sub menu, QDarkStyleSheet settings + // doesn't impact sub menu for unknown reason + if(darkMode) { + compactMenu->setStyleSheet(subMenuStyleSheet); + } + } + i = j; + } +} + +ScintillaNext *MainWindow::currentEditor() const +{ + return dockedEditor->getCurrentEditor(); +} + +int MainWindow::editorCount() const +{ + return dockedEditor->count(); +} + +QVector MainWindow::editors() const +{ + // NOTE: this will need re-evaluated in the future. + // So far it has been assumed 1 ScintillaNext instance is 1 DockedEditor widget instance. + // If in the future a ScintillaNext can be cloned then the DockedEditor could return + // the same ScintillaNext instance multiple times since 1 ScintillaNext could mean >= 1 DockedEditor widget instance + return dockedEditor->editors(); +} + +void MainWindow::newFile() +{ + qInfo(Q_FUNC_INFO); + + static int count = 1; + + // NOTE: in theory need to check all editors in the editorManager to future proof this. + // If there is another window it would need to check those too to see if New X exists. The editor + // manager would encompass all editors + + forever { + QString newFileName = tr("New %1").arg(count++); + bool canUseName = true; + + for (const ScintillaNext *editor : editors()) { + if (!editor->isFile() && editor->getName() == newFileName) { + canUseName = false; + break; + } + } + + if (canUseName) { + app->getEditorManager()->createEditor(newFileName); + break; + } + } +} + +// One unedited, new blank document +ScintillaNext *MainWindow::getInitialEditor() +{ + if (editorCount() == 1) { + ScintillaNext *editor = currentEditor(); + + // If the editor has had ANY modifications, then don't call it an initial editor + if (!editor->isFile() && !editor->canUndo() && !editor->canRedo()) { + return editor; + } + } + + return Q_NULLPTR; +} + +void MainWindow::openFileList(const QStringList &fileNames) +{ + qInfo(Q_FUNC_INFO); + + if (fileNames.size() == 0) + return; + + ScintillaNext *initialEditor = getInitialEditor(); + const ScintillaNext *mostRecentEditor = Q_NULLPTR; + + for (const QString &filePath : fileNames) { + qInfo("%s", qUtf8Printable(filePath)); + + // Search currently open editors to see if it is already open + ScintillaNext *editor = app->getEditorManager()->getEditorByFilePath(filePath); + + if (editor == Q_NULLPTR) { + QFileInfo fileInfo(filePath); + + if (!fileInfo.isFile()) { + auto reply = QMessageBox::question(this, tr("Create File"), tr("%1 does not exist. Do you want to create it?").arg(filePath)); + + if (reply == QMessageBox::Yes) { + editor = app->getEditorManager()->createEditorFromFile(filePath, true); + } + else { + // Make sure it is not still in the recent files list still. + // Normally when a file is opened it is removed from the file list, + // but if a user doesn't want to create the file, remove it explicitly. + app->getRecentFilesListManager()->removeFile(filePath); + continue; + } + } + else { + editor = app->getEditorManager()->createEditorFromFile(filePath); + } + } + + if (editor) { + mostRecentEditor = editor; + } + } + + // If any were successful, switch to the last one + if (mostRecentEditor) { + dockedEditor->switchToEditor(mostRecentEditor); + } + + if (initialEditor) { + initialEditor->close(); + } +} + +bool MainWindow::checkEditorsBeforeClose(const QVector &editors) +{ + for (ScintillaNext *editor : editors) { + if (!editor->isSavedToDisk()) { + // Switch to it + dockedEditor->switchToEditor(editor); + + // Ask the user what to do + QString message = tr("Save file %1?").arg(editor->getName()); + auto reply = QMessageBox::question(this, tr("Save File"), message, QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save); + + if (reply == QMessageBox::Cancel) { + // Stop checking and let the caller know + return false; + } + else if (reply == QMessageBox::Save) { + bool didFileGetSaved = saveFile(editor); + + // The user might have canceled the save file dialog so just stop now + if (didFileGetSaved == false) { + // Stop checking and let the caller know + return false; + } + } + } + } + + // Everything is fine + return true; +} + +void MainWindow::openFileDialog() +{ + QString dialogDir; + const QString filter = app->getFileDialogFilter(); + const ScintillaNext *editor = currentEditor(); + + // Use the path if possible + if (editor->isFile()) { + dialogDir = editor->getPath(); + } + + QStringList fileNames = FileDialogHelpers::getOpenFileNames(this, QString(), dialogDir, filter); + + openFileList(fileNames); +} + +void MainWindow::openFile(const QString &filePath) +{ + openFileList(QStringList() << filePath); +} + +void MainWindow::openFolderAsWorkspaceDialog() +{ + QString dialogDir; + const ScintillaNext *editor = currentEditor(); + + // Use the path if possible + if (editor->isFile()) { + dialogDir = editor->getPath(); + } + + QString dir = QFileDialog::getExistingDirectory(this, tr("Open Folder as Workspace"), dialogDir, QFileDialog::ShowDirsOnly); + + if (!dir.isEmpty()) { + FolderAsWorkspaceDock *fawDock = findChild(); + fawDock->setRootPath(dir); + fawDock->setVisible(true); + } +} + +void MainWindow::reloadFile() +{ + auto editor = currentEditor(); + + if (!editor->isFile() && !editor->isSavedToDisk()) { + return; + } + + const QString filePath = editor->getFilePath(); + auto reply = QMessageBox::question(this, tr("Reload File"), tr("Are you sure you want to reload %1? Any unsaved changes will be lost.").arg(filePath)); + + if (reply == QMessageBox::Yes) { + editor->reload(); + } +} + +void MainWindow::closeCurrentFile() +{ + closeFile(currentEditor()); +} + +void MainWindow::closeFile(ScintillaNext *editor) +{ + // Early out. If we aren't exiting on last tab closed, and it exists, there's no point in continuing + if (!app->getSettings()->exitOnLastTabClosed() && getInitialEditor() != Q_NULLPTR) { + return; + } + + if(editor->isSavedToDisk()) { + editor->close(); + } + else { + // The user needs be asked what to do about this file, so switch to it + dockedEditor->switchToEditor(editor); + + QString message = tr("Save file %1?").arg(editor->getName()); + auto reply = QMessageBox::question(this, tr("Save File"), message, QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save); + + if (reply == QMessageBox::Cancel) { + return; + } + + if (reply == QMessageBox::Save) { + bool didFileGetSaved = saveFile(editor); + + // The user might have canceled the save file dialog so just stop now + if (didFileGetSaved == false) + return; + } + + editor->close(); + } + + // If the last document was closed, figure out what to do next + if (editorCount() == 0) { + if (app->getSettings()->exitOnLastTabClosed()) { + close(); + } + else { + newFile(); + } + } +} + +void MainWindow::closeAllFiles() +{ + if (!checkEditorsBeforeClose(editors())) { + return; + } + + // Ask the manager to close the editors the dockedEditor knows about + for (ScintillaNext *editor : editors()) { + editor->close(); + } + + newFile(); +} + +void MainWindow::closeAllExceptActive() +{ + auto e = currentEditor(); + auto editor_list = editors(); + + editor_list.removeOne(e); + + if (checkEditorsBeforeClose(editor_list)) { + for (ScintillaNext *editor : editor_list) { + editor->close(); + } + } +} + +void MainWindow::closeAllToLeft() +{ + const int index = dockedEditor->currentDockArea()->currentIndex(); + QVector editors; + + for (int i = 0; i < index; ++i) { + auto editor = qobject_cast(dockedEditor->currentDockArea()->dockWidget(i)->widget()); + editors.append(editor); + } + + if (checkEditorsBeforeClose(editors)) { + for (ScintillaNext *editor : editors) { + editor->close(); + } + } +} + +void MainWindow::closeAllToRight() +{ + const int index = dockedEditor->currentDockArea()->currentIndex(); + const int total = dockedEditor->currentDockArea()->dockWidgetsCount(); + QVector editors; + + for (int i = index + 1; i < total; ++i) { + auto editor = qobject_cast(dockedEditor->currentDockArea()->dockWidget(i)->widget()); + editors.append(editor); + } + + if (checkEditorsBeforeClose(editors)) { + for (ScintillaNext *editor : editors) { + editor->close(); + } + } +} + +bool MainWindow::saveCurrentFile() +{ + return saveFile(currentEditor()); +} + +bool MainWindow::saveFile(ScintillaNext *editor) +{ + if (editor->isSavedToDisk()) + return true; + + if (!editor->isFile()) { + // Switch to the editor and show the saveas dialog + dockedEditor->switchToEditor(editor); + return saveCurrentFileAsDialog(); + } + else { + QFileDevice::FileError error = editor->save(); + if (error == QFileDevice::NoError) { + return true; + } + else { + showSaveErrorMessage(editor, error); + return false; + } + } +} + +bool MainWindow::saveCurrentFileAsDialog() +{ + QString dialogDir; + const QString filter = app->getFileDialogFilter(); + ScintillaNext *editor = currentEditor(); + + // Use the file path if possible + if (editor->isFile()) { + dialogDir = editor->getFilePath(); + } + + QString selectedFilter = app->getFileDialogFilterForLanguage(editor->languageName); + QString fileName = FileDialogHelpers::getSaveFileName(this, QString(), dialogDir, filter, &selectedFilter); + + if (fileName.size() == 0) { + return false; + } + + // TODO: distinguish between the above case (i.e. the user cancels the dialog) and a failure + // calling editor->saveAs() as it might fail. + + return saveFileAs(editor, fileName); +} + +bool MainWindow::saveCurrentFileAs(const QString &fileName) +{ + return saveFileAs(currentEditor(), fileName); +} + +bool MainWindow::saveFileAs(ScintillaNext *editor, const QString &fileName) +{ + qInfo("saveFileAs(%s)", qUtf8Printable(fileName)); + + QFileDevice::FileError error = editor->saveAs(fileName); + + if (error == QFileDevice::NoError) { + return true; + } + else { + showSaveErrorMessage(editor, error); + return false; + } +} + +bool MainWindow::saveCopyAsDialog() +{ + QString dialogDir; + const QString filter = app->getFileDialogFilter(); + const ScintillaNext* editor = currentEditor(); + + // Use the file path if possible + if (editor->isFile()) { + dialogDir = editor->getFilePath(); + } + + QString selectedFilter = app->getFileDialogFilterForLanguage(editor->languageName); + QString fileName = FileDialogHelpers::getSaveFileName(this, tr("Save a Copy As"), dialogDir, filter, &selectedFilter); + + if (fileName.size() == 0) { + return false; + } + + return saveCopyAs(fileName); +} + +bool MainWindow::saveCopyAs(const QString &fileName) +{ + auto editor = currentEditor(); + + QFileDevice::FileError error = editor->saveCopyAs(fileName); + + if (error == QFileDevice::NoError) { + return true; + } + else { + showSaveErrorMessage(editor, error); + return false; + } +} + +void MainWindow::saveAll() +{ + for (ScintillaNext *editor : editors()) { + saveFile(editor); + } +} + +void MainWindow::exportAsFormat(Converter *converter, const QString &filter) +{ + const QString fileName = FileDialogHelpers::getSaveFileName(this, tr("Export As"), QString(), filter + ";;All files (*)"); + + if (fileName.isEmpty()) { + return; + } + + QFile f(fileName); + + f.open(QIODevice::WriteOnly); + + QTextStream s(&f); + converter->convert(s); + f.close(); +} + +void MainWindow::copyAsFormat(Converter *converter, const QString &mimeType) +{ + // This is not ideal as we are *assuming* the converter is currently associated with the currentEditor() + ScintillaNext *editor = currentEditor(); + QByteArray buffer; + QTextStream stream(&buffer); + + if (editor->selectionEmpty()) + converter->convert(stream); + else { + converter->convertRange(stream, editor->selectionStart(), editor->selectionEnd()); + } + + QMimeData *mimeData = new QMimeData(); + mimeData->setData(mimeType, buffer); + + QApplication::clipboard()->setMimeData(mimeData); +} + +void MainWindow::renameFile() +{ + ScintillaNext *editor = currentEditor(); + + if (editor->isFile()) { + const QString filter = app->getFileDialogFilter(); + QString selectedFilter = app->getFileDialogFilterForLanguage(editor->languageName); + QString fileName = FileDialogHelpers::getSaveFileName(this, tr("Rename"), editor->getFilePath(), filter, &selectedFilter); + + if (fileName.isEmpty()) { + return; + } + + // TODO + // The new fileName might be to one of the existing editors. + //auto otherEditor = app->getEditorByFilePath(fileName); + + bool renameSuccessful = editor->rename(fileName); + Q_UNUSED(renameSuccessful) + } + else { + bool ok; + QString text = QInputDialog::getText(this, tr("Rename"), tr("Name:"), QLineEdit::Normal, editor->getName(), &ok); + + if (ok && !text.isEmpty()) { + editor->setName(text); + } + } +} + +void MainWindow::moveCurrentFileToTrash() +{ + ScintillaNext *editor = currentEditor(); + + moveFileToTrash(editor); +} + +void MainWindow::moveFileToTrash(ScintillaNext *editor) +{ + Q_ASSERT(editor->isFile()); + + const QString filePath = editor->getFilePath(); + auto reply = QMessageBox::question(this, tr("Delete File"), tr("Are you sure you want to move %1 to the trash?").arg(filePath)); + + if (reply == QMessageBox::Yes) { + if (editor->moveToTrash()) { + closeCurrentFile(); + + // Since the file no longer exists, specifically remove it from the recent files list + app->getRecentFilesListManager()->removeFile(editor->getFilePath()); + } + else { + QMessageBox::warning(this, tr("Error Deleting File"), tr("Something went wrong deleting %1?").arg(filePath)); + } + } +} + +void MainWindow::print() +{ + QPrintPreviewDialog printDialog(this, Qt::Window); + EditorPrintPreviewRenderer renderer(currentEditor()); + + connect(&printDialog, &QPrintPreviewDialog::paintRequested, &renderer, &EditorPrintPreviewRenderer::render); + + // TODO: load/save the page layout that was used and reload it next time + //preview.printer()->setPageLayout( /* todo */ ); + + printDialog.printer()->setPageMargins(QMarginsF(.5, .5, .5, .5), QPageLayout::Inch); + + connect(&printDialog, &QPrintPreviewDialog::accepted, this, [&]() { + qInfo() << printDialog.printer()->pageLayout(); + }); + + printDialog.exec(); +} + +void MainWindow::convertEOLs(int eolMode) +{ + ScintillaNext *editor = currentEditor(); + + // TODO: does convertEOLs trigger SCN_MODIFIED notifications? If so can these be turned off to increase performance? + editor->convertEOLs(eolMode); + editor->setEOLMode(eolMode); + + updateEOLBasedUi(editor); + + // There's no simple Scintilla notification that the EOL mode has changed + // So tell the status bar to refresh its info + ui->statusBar->refresh(editor); +} + +void MainWindow::showFindReplaceDialog(int index) +{ + ScintillaNext *editor = currentEditor(); + FindReplaceDialog *frd = findChild(QString(), Qt::FindDirectChildrenOnly); + + if (frd == Q_NULLPTR) { + frd = new FindReplaceDialog(determineSearchResultsHandler(), this); + } + else { + frd->setSearchResultsHandler(determineSearchResultsHandler()); + } + + // TODO: if dockedEditor::editorActivated() is fired, or if the editor get closed + // the FindReplaceDialog's editor pointer needs updated... + + // Get any selected text + if (!editor->selectionEmpty()) { + int selection = editor->mainSelection(); + int start = editor->selectionNStart(selection); + int end = editor->selectionNEnd(selection); + if (end > start) { + auto selText = editor->get_text_range(start, end); + frd->setFindString(QString::fromUtf8(selText)); + } + } + else { + int start = editor->wordStartPosition(editor->currentPos(), true); + int end = editor->wordEndPosition(editor->currentPos(), true); + if (end > start) { + editor->setSelectionStart(start); + editor->setSelectionEnd(end); + auto selText = editor->get_text_range(start, end); + frd->setFindString(QString::fromUtf8(selText)); + } + } + + frd->setTab(index); + frd->show(); + frd->raise(); + frd->activateWindow(); +} + +void MainWindow::updateFileStatusBasedUi(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + bool isFile = editor->isFile(); + QString fileName; + + if (isFile) { + fileName = editor->getFilePath(); + } + else { + fileName = editor->getName(); + } + + QString title = QStringLiteral("[*]%1").arg(fileName); + if (app->isRunningAsAdmin()) { + title += QStringLiteral(" - [%1]").arg(tr("Administrator")); + } + setWindowTitle(title); + + ui->actionReload->setEnabled(isFile); + ui->actionMoveToTrash->setEnabled(isFile); + ui->actionCopyFullPath->setEnabled(isFile); + ui->actionCopyFileDirectory->setEnabled(isFile); + ui->actionShowInExplorer->setEnabled(isFile); + ui->actionOpenCommandPromptHere->setEnabled(isFile); +} + +bool MainWindow::isAnyUnsaved() const +{ + for (const ScintillaNext *editor : editors()) { + if (!editor->isSavedToDisk()) { + return true; + } + } + + return false; +} + +void MainWindow::updateEOLBasedUi(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + switch(editor->eOLMode()) { + case SC_EOL_CR: + ui->actionMacintosh->setChecked(true); + break; + case SC_EOL_CRLF: + ui->actionWindows->setChecked(true); + break; + case SC_EOL_LF: + ui->actionUnix->setChecked(true); + break; + } +} + +void MainWindow::updateSaveStatusBasedUi(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + bool isDirty = !editor->isSavedToDisk(); + + setWindowModified(isDirty); + + ui->actionSave->setEnabled(isDirty); + ui->actionSaveAll->setEnabled(isDirty || isAnyUnsaved()); + + if (editorCount() == 1) { + bool ableToClose = editor->isFile() || isDirty; + ui->actionClose->setEnabled(ableToClose); + ui->actionCloseAll->setEnabled(ableToClose); + } + else { + ui->actionClose->setEnabled(true); + ui->actionCloseAll->setEnabled(true); + } +} + +void MainWindow::updateEditorPositionBasedUi() +{ + const int index = dockedEditor->currentDockArea()->currentIndex(); + const int total = dockedEditor->currentDockArea()->dockWidgetsCount(); + + ui->actionCloseAllToLeft->setEnabled(index > 0); + ui->actionCloseAllToRight->setEnabled(index < (total - 1)); + ui->actionCloseAllExceptActive->setEnabled(editorCount() > 1); +} + +void MainWindow::updateLanguageBasedUi(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + const QString language_name = editor->languageName; + + for (QAction *action : languageActionGroup->actions()) { + if (action->data().toString() == language_name) { + action->setChecked(true); + + // Found one, so we are completely done + return; + } + } + + // The above loop did not set any action as checked, so make sure they are all unchecked now + for (QAction *action : languageActionGroup->actions()) { + if (action->isChecked()) { + action->setChecked(false); + } + } +} + +void MainWindow::updateGui(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + updateFileStatusBasedUi(editor); + updateSaveStatusBasedUi(editor); + updateEOLBasedUi(editor); + updateEditorPositionBasedUi(); + updateSelectionBasedUi(editor); + updateContentBasedUi(editor); + updateLanguageBasedUi(editor); +} + +void MainWindow::updateDocumentBasedUi(Scintilla::Update updated) +{ + ScintillaNext *editor = qobject_cast(sender()); + + // TODO: what if this is triggered by an editor that is not the active editor? + + if (Scintilla::FlagSet(updated, Scintilla::Update::Content)) { + updateSelectionBasedUi(editor); + } + + if (Scintilla::FlagSet(updated, Scintilla::Update::Content) || Scintilla::FlagSet(updated, Scintilla::Update::Selection)) { + updateContentBasedUi(editor); + } +} + +void MainWindow::updateSelectionBasedUi(ScintillaNext *editor) +{ + ui->actionUndo->setEnabled(editor->canUndo()); + ui->actionRedo->setEnabled(editor->canRedo()); +} + +void MainWindow::updateContentBasedUi(ScintillaNext *editor) +{ + bool hasAnySelections = !editor->selectionEmpty(); + + ui->actionPaste->setEnabled(editor->canPaste()); + + ui->actionLowerCase->setEnabled(hasAnySelections); + ui->actionUpperCase->setEnabled(hasAnySelections); + + ui->actionBase64Encode->setEnabled(hasAnySelections); + ui->actionURLEncode->setEnabled(hasAnySelections); + ui->actionBase64Decode->setEnabled(hasAnySelections); + ui->actionURLDecode->setEnabled(hasAnySelections); +} + +void MainWindow::detectLanguage(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + if (!editor->isFile()) { + // Default to some specific language if it is not a file. + setLanguage(editor, "Text"); + return; + } + else { + const QString language_name = app->detectLanguage(editor); + + setLanguage(editor, language_name); + } + + return; +} + +void MainWindow::activateEditor(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + checkFileForModification(editor); + updateGui(editor); + + emit editorActivated(editor); +} + +void MainWindow::applyStyleSheet() +{ + qInfo(Q_FUNC_INFO); + + // Notepad next default style sheet + QString cssContent = loadCssFile(":/stylesheets/npp.css"); + if (app->getSettings()->darkMode()) { + // QDarkStyleSheet dark theme + QString darkCss = loadCssFile(":/qdarkstyle/dark/style.qss"); + cssContent.append(darkCss); + + // further tweak + QString nppDark= loadCssFile(":/stylesheets/npp-dark.css"); + cssContent.append(nppDark); + } + + // If there is a "custom.css" file where the ini is located, load it as a style sheet addition + QString directoryPath = QFileInfo(app->getSettings()->fileName()).absolutePath(); + QString fullPath = QDir(directoryPath).filePath("custom.css"); + if (QFile::exists(fullPath)) { + QFile custom(fullPath); + qInfo() << "Loading stylesheet: " << custom.fileName(); + + custom.open(QFile::ReadOnly); + cssContent.append(custom.readAll()); + custom.close(); + } + + setStyleSheet(cssContent); +} + +void MainWindow::setLanguage(ScintillaNext *editor, const QString &languageName) +{ + qInfo(Q_FUNC_INFO); + qInfo("Language Name: %s", qUtf8Printable(languageName)); + + app->setEditorLanguage(editor, languageName); +} + +void MainWindow::bringWindowToForeground() +{ + qInfo(Q_FUNC_INFO); + + // There doesn't seem to be a cross platform way to force the window to the foreground + +#ifdef Q_OS_WIN + HWND hWnd = reinterpret_cast(effectiveWinId()); + + if (hWnd) { + // I have no idea what this does, but it seems to work on Windows + // References: + // https://stackoverflow.com/questions/916259/win32-bring-a-window-to-top + // https://github.com/notepad-plus-plus/notepad-plus-plus/blob/ebe7648ee1a5a560d4fc65297cbdcf08055e56e3/PowerEditor/src/winmain.cpp#L596 + + HWND hCurWnd = GetForegroundWindow(); + DWORD threadId = GetCurrentThreadId(); + DWORD procId = GetWindowThreadProcessId(hCurWnd, NULL); + + int sw = 0; + if (IsZoomed(hWnd)) { + sw = SW_MAXIMIZE; + } else if (IsIconic(hWnd)) { + sw = SW_RESTORE; + } + + if (sw != 0) { + ShowWindow(hWnd, sw); + } + + AttachThreadInput(procId, threadId, TRUE); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + AttachThreadInput(procId, threadId, FALSE); + } +#else + setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); + raise(); + activateWindow(); +#endif +} + +bool MainWindow::checkFileForModification(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + auto state = editor->checkFileForStateChange(); + + if (state == ScintillaNext::NoChange) { + return false; + } + else if (state == ScintillaNext::Modified) { + qInfo("ScintillaNext::Modified"); + editor->reload(); + } + else if (state == ScintillaNext::Deleted) { + qInfo("ScintillaNext::Deleted"); + } + else if (state == ScintillaNext::Restored) { + qInfo("ScintillaNext::Restored"); + } + + return true; +} + +void MainWindow::showSaveErrorMessage(ScintillaNext *editor, QFileDevice::FileError error) +{ + const QString name = editor->isFile() ? editor->getFilePath() : editor->getName(); + QMessageBox::warning(this, tr("Error Saving File"), tr("An error occurred when saving %1

Error: %2").arg(name, qt_error_string(error))); +} + +void MainWindow::showEditorZoomLevelIndicator() +{ + // Not sure if Scintilla's zoom level matches up to an exact percentage, but visibly this is close + FadingIndicator::showText(currentEditor(), tr("Zoom: %1%").arg(zoomLevel * 10 + 100)); +} + +void MainWindow::saveSettings() const +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings *settings = app->getSettings(); + + settings->setValue("MainWindow/geometry", saveGeometry()); + settings->setValue("MainWindow/windowState", saveState()); + + settings->setValue("Editor/ZoomLevel", zoomLevel); +} + +void MainWindow::restoreSettings() +{ + qInfo(Q_FUNC_INFO); + + ApplicationSettings *settings = app->getSettings(); + + zoomLevel = settings->value("Editor/ZoomLevel", 0).toInt(); +} + +ISearchResultsHandler *MainWindow::determineSearchResultsHandler() +{ + // Determine what will get the search results + if (app->getSettings()->combineSearchResults()) { + searchResults.reset(new SearchResultsCollector(findChild())); + + return searchResults.data(); + } + else { + return findChild(); + } +} + +void MainWindow::restoreWindowState() +{ + ApplicationSettings *settings = app->getSettings(); + + restoreGeometry(settings->value("MainWindow/geometry").toByteArray()); + restoreState(settings->value("MainWindow/windowState").toByteArray()); + + // Always hide the dock no matter how the application was closed + SearchResultsDock *srDock = findChild(); + srDock->hide(); +} + +void MainWindow::switchToEditor(const ScintillaNext *editor) +{ + dockedEditor->switchToEditor(editor); +} + +void MainWindow::focusIn() +{ + qInfo(Q_FUNC_INFO); + + if (checkFileForModification(currentEditor())) { + updateGui(currentEditor()); + } +} + +void MainWindow::addEditor(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + detectLanguage(editor); + + // These should only ever occur for the focused editor?? + // TODO: look at editor inspector as an example to ensure updates are only coming from one editor. + // Can save the connection objects and disconnected from them and only connect to the editor as it is activated. + connect(editor, &ScintillaNext::savePointChanged, this, [=]() { updateSaveStatusBasedUi(editor); }); + connect(editor, &ScintillaNext::renamed, this, [=]() { detectLanguage(editor); }); + connect(editor, &ScintillaNext::renamed, this, [=]() { updateFileStatusBasedUi(editor); }); + connect(editor, &ScintillaNext::updateUi, this, &MainWindow::updateDocumentBasedUi); + + // Watch for any zoom events (Ctrl+Scroll or pinch-to-zoom (Qt translates it as Ctrl+Scroll)) so that the event + // can be handled before the ScintillaEditBase widget, so that it can be applied to all editors to keep zoom level equal. + // NOTE: Need to install this on the scroll area's viewport, not on the editor widget itself...that was painful to learn + editor->viewport()->installEventFilter(zoomEventWatcher); + + editor->setZoom(zoomLevel); + + editor->setContextMenuPolicy(Qt::CustomContextMenu); + connect(editor, &ScintillaNext::customContextMenuRequested, this, [=](const QPoint &pos) { + contextMenuPos = editor->send(SCI_POSITIONFROMPOINT, pos.x(), pos.y()); + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + + URLFinder *urlFinder = editor->findChild(QString(), Qt::FindDirectChildrenOnly); + if (urlFinder && urlFinder->isEnabled() && urlFinder->isURL(contextMenuPos)) { + menu->addAction(ui->actionCopyURL); + menu->addSeparator(); + } + menu->addAction(ui->actionCut); + menu->addAction(ui->actionCopy); + menu->addAction(ui->actionPaste); + menu->addAction(ui->actionDelete); + menu->addSeparator(); + menu->addAction(ui->actionSelectAll); + menu->addSeparator(); + menu->addAction(ui->actionBase64Encode); + menu->addAction(ui->actionURLEncode); + menu->addSeparator(); + menu->addAction(ui->actionBase64Decode); + menu->addAction(ui->actionURLDecode); + menu->popup(QCursor::pos()); + }); + + // The editor has been entirely configured at this point, so add it to the docked editor + dockedEditor->addEditor(editor); +} + +void MainWindow::checkForUpdates(bool silent) +{ +#ifdef Q_OS_WIN + qInfo(Q_FUNC_INFO); + + QString url = "https://github.com/dail8859/NotepadNext/raw/master/updates.json"; + QSimpleUpdater::getInstance()->checkForUpdates(url); + + if (!silent) { + connect(QSimpleUpdater::getInstance(), &QSimpleUpdater::checkingFinished, this, &MainWindow::checkForUpdatesFinished, Qt::UniqueConnection); + } + else { + disconnect(QSimpleUpdater::getInstance(), &QSimpleUpdater::checkingFinished, this, &MainWindow::checkForUpdatesFinished); + } + + + app->getSettings()->setValue("App/LastUpdateCheck", QDateTime::currentDateTime()); +#else + Q_UNUSED(silent); +#endif +} + +void MainWindow::checkForUpdatesFinished(QString url) +{ +#ifdef Q_OS_WIN + if (!QSimpleUpdater::getInstance()->getUpdateAvailable(url)) { + QMessageBox::information(this, QString(), tr("No updates are available at this time.")); + } +#endif +} + +void MainWindow::initUpdateCheck() +{ +#ifdef Q_OS_WIN +#ifdef QT_DEBUG + if (true) { +#else + QSettings registry(QSettings::NativeFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationName()); + const bool autoUpdatesEnabled = registry.value("AutoUpdate", 0).toBool(); + qInfo("AutoUpdates: %d", autoUpdatesEnabled); + + if (autoUpdatesEnabled) { +#endif + connect(ui->actionCheckForUpdates, &QAction::triggered, this, &MainWindow::checkForUpdates); + + // A bit after startup, see if we need to automatically check for an update + QTimer::singleShot(15000, this, [=]() { + ApplicationSettings settings; + QDateTime dt = settings.value("App/LastUpdateCheck", QDateTime::currentDateTime()).toDateTime(); + + if (dt.isValid()) { + qInfo("Last checked for updates at: %s", qUtf8Printable(dt.toString())); + + if (dt.addDays(7) < QDateTime::currentDateTime()) { + checkForUpdates(true); + } + } + }); + } + else { + ui->actionCheckForUpdates->setDisabled(true); + ui->actionCheckForUpdates->setVisible(false); + } +#else + ui->actionCheckForUpdates->setDisabled(true); + ui->actionCheckForUpdates->setVisible(false); +#endif +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + const SessionManager *sessionManager = app->getSessionManager(); + QVector e; + + // Check all editors to see if the session manager will not handle it + for (auto editor : editors()) { + if (!sessionManager->willFileGetStoredInSession(editor)) { + e.append(editor); + } + } + + if (!checkEditorsBeforeClose(e)) { + event->ignore(); + return; + } + + emit aboutToClose(); + + event->accept(); + + QMainWindow::closeEvent(event); +} + +void MainWindow::dragEnterEvent(QDragEnterEvent *event) +{ + qInfo(Q_FUNC_INFO); + + // NOTE: for urls these can be dragged anywhere in the application, editor, tabs, menu + // because the ScintillaNext editor ignores urls so they can be handled by the main + // application + // Text dragging within the editor object itself is handled by Scintilla, but if the text + // is dragged to other parts (tabs, menu, etc) it will be handled by the application to + // create a new editor from the text. + + // Accept urls and text + if (event->mimeData()->hasUrls() || event->mimeData()->hasText()) { + event->acceptProposedAction(); + } + else { + event->ignore(); + } +} + +void MainWindow::dropEvent(QDropEvent *event) +{ + qInfo(Q_FUNC_INFO); + + if (event->mimeData()->hasUrls()) { + // Get the urls into a stringlist + QStringList fileNames; + for (const QUrl &url : event->mimeData()->urls()) { + if (url.isLocalFile()) { + QFileInfo info(url.toLocalFile()); + + if (info.exists()) { + if (info.isDir()) { + QDirIterator it(url.toLocalFile(), QDir::Files, QDirIterator::FollowSymlinks| QDirIterator::Subdirectories); + while (it.hasNext()) { + fileNames << it.next(); + } + } + else { + fileNames.append(url.toLocalFile()); + } + } + } + } + + openFileList(fileNames); + bringWindowToForeground(); + event->acceptProposedAction(); + } + else if (event->mimeData()->hasText()) { + if (event->source()) { + // if it is from an editor, remove the text + ScintillaNext *sn = qobject_cast(event->source()); + if (sn) { + sn->replaceSel(""); + } + } + + newFile(); + currentEditor()->setText(event->mimeData()->text().toLocal8Bit().constData()); + bringWindowToForeground(); + event->acceptProposedAction(); + } + else { + event->ignore(); + } +} + +void MainWindow::tabBarRightClicked(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + // Focus on the correct tab + dockedEditor->switchToEditor(editor); + + // Create the menu + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + + // Default actions + QStringList actionNames{ + "Close", + "CloseAllExceptActive", + "CloseAllToLeft", + "CloseAllToRight", + "", + "Save", + "SaveAs", + "Rename", + "", + "Reload", + "", +#ifdef Q_OS_WIN + "ShowInExplorer", + "OpenCommandPromptHere", + "", +#endif + "CopyFullPath", + "CopyFileName", + "CopyFileDirectory" + }; + + // If the entry exists in the settings, use that + ApplicationSettings *settings = app->getSettings(); + if (settings->contains("Gui/TabBarContextMenu")) { + actionNames = settings->value("Gui/TabBarContextMenu").toStringList(); + } + + // Populate the menu + for (const QString &actionName : actionNames) { + if (actionName.isEmpty()) { + menu->addSeparator(); + } + else { + QAction *a = findChild(QStringLiteral("action") + actionName, Qt::FindDirectChildrenOnly); + + if (a != Q_NULLPTR) { + menu->addAction(a); + } + else { + qWarning() << "Cannot locate menu named" << actionName; + } + } + } + + // Show it + menu->popup(QCursor::pos()); +} + +void MainWindow::languageMenuTriggered() +{ + const QAction *act = qobject_cast(sender()); + auto editor = currentEditor(); + QVariant v = act->data(); + + setLanguage(editor, v.toString()); +} + +ApplicationSettings* MainWindow::getSettings() +{ + return app->getSettings(); +} diff --git a/src/NotepadNext/dialogs/MainWindow.h b/src/NotepadNext/dialogs/MainWindow.h new file mode 100644 index 000000000..4242375bc --- /dev/null +++ b/src/NotepadNext/dialogs/MainWindow.h @@ -0,0 +1,178 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include + +#include "DockedEditor.h" + +#include "MacroManager.h" +#include "ScintillaNext.h" +#include "NppImporter.h" +#include "SearchResultsCollector.h" +#include "ApplicationSettings.h" + +namespace Ui { +class MainWindow; +} + +class NotepadNextApplication; +class Macro; +class QuickFindWidget; +class ZoomEventWatcher; +class Converter; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(NotepadNextApplication *app); + ~MainWindow() override; + + bool isAnyUnsaved() const; + + void setupLanguageMenu(); + ScintillaNext *currentEditor() const; + int editorCount() const; + QVector editors() const; + DockedEditor *getDockedEditor() const { return dockedEditor; } + +public slots: + void newFile(); + + void openFileDialog(); + void openFile(const QString &filePath); + + void openFolderAsWorkspaceDialog(); + + void reloadFile(); + + void closeCurrentFile(); + void closeFile(ScintillaNext *editor); + void closeAllFiles(); + void closeAllExceptActive(); + void closeAllToLeft(); + void closeAllToRight(); + + bool saveCurrentFile(); + bool saveFile(ScintillaNext *editor); + + bool saveCurrentFileAsDialog(); + bool saveCurrentFileAs(const QString &fileName); + bool saveFileAs(ScintillaNext *editor, const QString &fileName); + + bool saveCopyAsDialog(); + bool saveCopyAs(const QString &fileName); + void saveAll(); + + void exportAsFormat(Converter *converter, const QString &filter); + void copyAsFormat(Converter *converter, const QString &mimeType); + + void renameFile(); + + void moveCurrentFileToTrash(); + void moveFileToTrash(ScintillaNext *editor); + + void print(); + + void convertEOLs(int eolMode); + + void showFindReplaceDialog(int index); + + void updateFileStatusBasedUi(ScintillaNext *editor); + void updateEOLBasedUi(ScintillaNext *editor); + void updateDocumentBasedUi(Scintilla::Update updated); + void updateSelectionBasedUi(ScintillaNext *editor); + void updateContentBasedUi(ScintillaNext *editor); + void updateSaveStatusBasedUi(ScintillaNext *editor); + void updateEditorPositionBasedUi(); + void updateLanguageBasedUi(ScintillaNext *editor); + void updateGui(ScintillaNext *editor); + + void detectLanguage(ScintillaNext *editor); + + void setLanguage(ScintillaNext *editor, const QString &languageName); + + void bringWindowToForeground(); + void focusIn(); + + void addEditor(ScintillaNext *editor); + + void checkForUpdates(bool silent = false); + + void restoreWindowState(); + + void switchToEditor(const ScintillaNext *editor); + + ApplicationSettings* getSettings(); + +signals: + void editorActivated(ScintillaNext *editor); + void aboutToClose(); + +protected: + void closeEvent(QCloseEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + +private slots: + void tabBarRightClicked(ScintillaNext *editor); + void languageMenuTriggered(); + void checkForUpdatesFinished(QString url); + void activateEditor(ScintillaNext *editor); + +private: + Ui::MainWindow *ui = Q_NULLPTR; + NotepadNextApplication *app = Q_NULLPTR; + DockedEditor *dockedEditor = Q_NULLPTR; + + QScopedPointer searchResults; + + void applyStyleSheet(); + void applyCustomShortcuts(); + void initUpdateCheck(); + ScintillaNext *getInitialEditor(); + void openFileList(const QStringList &fileNames); + bool checkEditorsBeforeClose(const QVector &editors); + bool checkFileForModification(ScintillaNext *editor); + void showSaveErrorMessage(ScintillaNext *editor, QFileDevice::FileError error); + void showEditorZoomLevelIndicator(); + + void saveSettings() const; + void restoreSettings(); + + ISearchResultsHandler *determineSearchResultsHandler(); + + QActionGroup *languageActionGroup; + + //NppImporter *npp; + + MacroManager macroManager; + + ZoomEventWatcher *zoomEventWatcher; + int zoomLevel = 0; + int contextMenuPos = 0; +}; + +#endif // MAINWINDOW_H diff --git a/src/NotepadNext/dialogs/MainWindow.ui b/src/NotepadNext/dialogs/MainWindow.ui new file mode 100644 index 000000000..6b01a7c27 --- /dev/null +++ b/src/NotepadNext/dialogs/MainWindow.ui @@ -0,0 +1,1379 @@ + + + MainWindow + + + + 0 + 0 + 855 + 646 + + + + true + + + Notepad Next[*] + + + + + true + + + + 830 + 0 + 20 + 20 + + + + + + + + + + + + &File + + + + Close More + + + + + + + + &Recent Files + + + + + + + + + Export As + + + + + + + + + + + + + + + + + + + + + + + + + + + + &Edit + + + + Copy More + + + + + + + + Indent + + + + + + + EOL Conversion + + + + + + + + Convert Case + + + + + + + Line Operations + + + + + + + + + + + + Comment/Uncomment + + + + + + + + Copy As + + + + + + + Encoding/Decoding + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Search + + + + Bookmarks + + + + + + + + + + + + + + + + + + + + + + + &View + + + + &Zoom + + + + + + + + + Show Symbol + + + + + + + + + + + Fold Level + + + + + + + + + + + + + + Unfold Level + + + + + + + + + + + + + + + + + + + + + + + + + + Language + + + + + Settings + + + + + + Macro + + + + + + + + + + + Help + + + + + + + + + + Encoding + + + + + + + + + + + + + + + + Main Tool Bar + + + true + + + Qt::Horizontal + + + + 16 + 16 + + + + true + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + :/icons/newfile.png + + + + &New + + + Create a new file + + + Ctrl+N + + + + + + :/icons/openFile.png + + + + &Open... + + + Ctrl+O + + + Qt::WindowShortcut + + + + + + :/icons/saved.png + + + + &Save + + + Save + + + Ctrl+S + + + + + E&xit + + + QAction::QuitRole + + + + + + :/icons/undo.png + + + + &Undo + + + Ctrl+Z + + + + + + :/icons/redo.png + + + + &Redo + + + Ctrl+Y + + + + + + :/icons/cut.png + + + + Cu&t + + + Ctrl+X + + + + + + :/icons/copy.png + + + + &Copy + + + Ctrl+C + + + + + + :/icons/paste.png + + + + &Paste + + + Ctrl+V + + + + + &Delete + + + Del + + + + + Copy Full Path + + + + + Copy File Name + + + + + Copy File Directory + + + + + + :/icons/closeFile.png:/icons/closeFile.png + + + &Close + + + Close the current file + + + Ctrl+W + + + + + Save &As... + + + Ctrl+Alt+S + + + + + Save a Copy As... + + + + + + :/icons/saveAll.png:/icons/saveAll.png + + + Sav&e All + + + Ctrl+Shift+S + + + + + Select A&ll + + + Ctrl+A + + + + + + :/icons/text_indent.png:/icons/text_indent.png + + + Increase Indent + + + + + + :/icons/text_indent_remove.png:/icons/text_indent_remove.png + + + Decrease Indent + + + + + Rename... + + + + + + :/icons/arrow_refresh.png:/icons/arrow_refresh.png + + + Re&load + + + + + true + + + Windows (CR LF) + + + + + true + + + Unix (LF) + + + + + true + + + Macintosh (CR) + + + + + UPPER CASE + + + Convert text to upper case + + + + + lower case + + + Convert text to lower case + + + + + Duplicate Current Line + + + Alt+Down + + + + + Split Lines + + + + + Join Lines + + + Ctrl+J + + + + + Move Selected Lines Up + + + Ctrl+Shift+Up + + + + + Move Selected Lines Down + + + Ctrl+Shift+Down + + + + + + :/icons/closeAll.png:/icons/closeAll.png + + + Clos&e All + + + Close All files + + + Ctrl+Shift+W + + + + + Close All Except Active Document + + + + + Close All to the Left + + + + + Close All to the Right + + + + + + :/icons/zoomIn.png + + + + Zoom &In + + + Ctrl++ + + + + + + :/icons/zoomOut.png + + + + Zoom &Out + + + Ctrl+- + + + + + Reset Zoom + + + Ctrl+0 + + + + + About Qt + + + QAction::AboutQtRole + + + + + + :/icons/newfile.png:/icons/newfile.png + + + About Notepad Next + + + QAction::AboutRole + + + + + true + + + Show Whitespace + + + + + true + + + Show End of Line + + + + + true + + + + :/icons/invisibleChar.png + + + + Show All Characters + + + + + true + + + + :/icons/indentGuide.png + + + + Show Indent Guide + + + + + true + + + Show Wrap Symbol + + + + + true + + + + :/icons/wrap.png + + + + Word Wrap + + + + + Restore Recently Closed File + + + Ctrl+Shift+T + + + + + Open All Recent Files + + + + + Clear Recent Files List + + + + + + :/icons/find.png + + + + &Find... + + + Ctrl+F + + + + + Find in Files... + + + + + Find &Next + + + F3 + + + + + Find &Previous + + + + + + :/icons/findReplace.png + + + + &Replace... + + + Ctrl+H + + + + + true + + + Full Screen + + + F11 + + + + + true + + + + :/icons/startRecord.png + :/icons/stopRecord.png:/icons/startRecord.png + + + Start Recording + + + + + false + + + + :/icons/playRecord.png:/icons/playRecord.png + + + Playback + + + Ctrl+Shift+P + + + + + false + + + + :/icons/saveRecord.png:/icons/saveRecord.png + + + Save Current Recorded Macro... + + + + + false + + + + :/icons/playRecord_m.png:/icons/playRecord_m.png + + + Run a Macro Multiple Times... + + + + + + :/icons/cog.png:/icons/cog.png + + + Preferences... + + + QAction::PreferencesRole + + + + + Quick Find + + + Ctrl+Alt+I + + + + + Select Next Instance + + + Ctrl+D + + + + + + :/icons/bin_closed.png:/icons/bin_closed.png + + + Move to Trash... + + + Move to Trash + + + + + Check for Updates... + + + + + &Go to Line... + + + Ctrl+G + + + + + + :/icons/printer.png:/icons/printer.png + + + Print... + + + Ctrl+P + + + + + Open Folder as Workspace... + + + + + Toggle Single Line Comment + + + Ctrl+/ + + + + + Single Line Comment + + + Ctrl+K + + + + + Single Line Uncomment + + + Ctrl+Shift+K + + + + + false + + + + :/icons/table_edit.png:/icons/table_edit.png + + + Edit Macros... + + + + + false + + + This is not currently implemented + + + + + Column Mode... + + + + + Export as HTML... + + + + + Export as RTF... + + + + + Copy as HTML + + + + + Copy as RTF + + + + + Base 64 Encode + + + + + URL Encode + + + + + Base 64 Decode + + + + + URL Decode + + + + + Copy URL + + + + + Remove Empty Lines + + + + + + :/icons/folder_go.png:/icons/folder_go.png + + + Show in Explorer + + + Show in Explorer + + + + + + :/icons/application_osx_terminal.png:/icons/application_osx_terminal.png + + + Open Command Prompt Here + + + + + Toggle Bookmark + + + Ctrl+F2 + + + + + Next Bookmark + + + F2 + + + + + Previous Bookmark + + + Shift+F2 + + + + + Clear Bookmarks + + + + + Invert Bookmarks + + + + + Next Tab + + + Ctrl+Tab + + + QAction::NoRole + + + + + Previous Tab + + + Ctrl+Shift+Tab + + + QAction::NoRole + + + + + Fold Level 1 + + + Alt+1 + + + + + Fold Level 2 + + + Alt+2 + + + + + Fold Level 3 + + + Alt+3 + + + + + Fold Level 4 + + + Alt+4 + + + + + Unfold Level 1 + + + Alt+Shift+1 + + + + + Unfold Level 2 + + + Alt+Shift+2 + + + + + Unfold Level 3 + + + Alt+Shift+3 + + + + + Unfold Level 4 + + + Alt+Shift+4 + + + + + Fold All + + + Alt+0 + + + + + Unfold All + + + Alt+Shift+0 + + + + + Fold Level 5 + + + Alt+5 + + + + + Fold Level 6 + + + Alt+6 + + + + + Fold Level 7 + + + Alt+7 + + + + + Fold Level 8 + + + Alt+8 + + + + + Fold Level 9 + + + Alt+9 + + + + + Unfold Level 5 + + + Alt+Shift+5 + + + + + Unfold Level 6 + + + Alt+Shift+6 + + + + + Unfold Level 7 + + + Alt+Shift+7 + + + + + Unfold Level 8 + + + Alt+Shift+8 + + + + + Unfold Level 9 + + + Alt+Shift+9 + + + + + Toggle Overtype + + + Toggle Overtype + + + Ins + + + QAction::NoRole + + + + + + + EditorInfoStatusBar + QStatusBar +
EditorInfoStatusBar.h
+
+
+ + + + +
diff --git a/src/NotepadNext/dialogs/PreferencesDialog.cpp b/src/NotepadNext/dialogs/PreferencesDialog.cpp new file mode 100644 index 000000000..eb27e00b0 --- /dev/null +++ b/src/NotepadNext/dialogs/PreferencesDialog.cpp @@ -0,0 +1,139 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "PreferencesDialog.h" +#include "NotepadNextApplication.h" +#include "TranslationManager.h" +#include "ui_PreferencesDialog.h" + +#include + + +PreferencesDialog::PreferencesDialog(ApplicationSettings *settings, QWidget *parent) : + QDialog(parent, Qt::Tool), + ui(new Ui::PreferencesDialog), + settings(settings) +{ + ui->setupUi(this); + + QIcon icon = style()->standardIcon(QStyle::SP_MessageBoxInformation); + QPixmap pixmap = icon.pixmap(QSize(16, 16)); + ui->labelAppRestartIcon->setPixmap(pixmap); + ui->labelAppRestartIcon->hide(); + ui->labelAppRestart->hide(); + + MapSettingToCheckBox(ui->checkBoxMenuBar, &ApplicationSettings::showMenuBar, &ApplicationSettings::setShowMenuBar, &ApplicationSettings::showMenuBarChanged); + MapSettingToCheckBox(ui->checkBoxToolBar, &ApplicationSettings::showToolBar, &ApplicationSettings::setShowToolBar, &ApplicationSettings::showToolBarChanged); + MapSettingToCheckBox(ui->checkBoxStatusBar, &ApplicationSettings::showStatusBar, &ApplicationSettings::setShowStatusBar, &ApplicationSettings::showStatusBarChanged); + MapSettingToCheckBox(ui->checkBoxRecenterSearchDialog, &ApplicationSettings::centerSearchDialog, &ApplicationSettings::setCenterSearchDialog, &ApplicationSettings::centerSearchDialogChanged); + + MapSettingToGroupBox(ui->gbxRestorePreviousSession, &ApplicationSettings::restorePreviousSession, &ApplicationSettings::setRestorePreviousSession, &ApplicationSettings::restorePreviousSessionChanged); + + connect(ui->gbxRestorePreviousSession, &QGroupBox::toggled, this, [=](bool checked) { + if (!checked) { + ui->checkBoxUnsavedFiles->setChecked(false); + ui->checkBoxRestoreTempFiles->setChecked(false); + } + else { + QMessageBox::warning(this, tr("Warning"), tr("This feature is experimental and it should not be considered safe for critically important work. It may lead to possible data loss. Use at your own risk.")); + } + }); + + MapSettingToCheckBox(ui->checkBoxUnsavedFiles, &ApplicationSettings::restoreUnsavedFiles, &ApplicationSettings::setRestoreUnsavedFiles, &ApplicationSettings::restoreUnsavedFilesChanged); + MapSettingToCheckBox(ui->checkBoxRestoreTempFiles, &ApplicationSettings::restoreTempFiles, &ApplicationSettings::setRestoreTempFiles, &ApplicationSettings::restoreTempFilesChanged); + + MapSettingToCheckBox(ui->checkBoxCombineSearchResults, &ApplicationSettings::combineSearchResults, &ApplicationSettings::setCombineSearchResults, &ApplicationSettings::combineSearchResultsChanged); + + populateTranslationComboBox(); + connect(ui->comboBoxTranslation, QOverload::of(&QComboBox::currentIndexChanged), this, [=](int index) { + settings->setTranslation(ui->comboBoxTranslation->itemData(index).toString()); + showApplicationRestartRequired(); + }); + + MapSettingToCheckBox(ui->checkBoxExitOnLastTabClosed, &ApplicationSettings::exitOnLastTabClosed, &ApplicationSettings::setExitOnLastTabClosed, &ApplicationSettings::exitOnLastTabClosedChanged); + + MapSettingToCheckBox(ui->checkBoxDarkMode, &ApplicationSettings::darkMode, &ApplicationSettings::setDarkMode, &ApplicationSettings::darkModeChanged); + + ui->fcbDefaultFont->setCurrentFont(QFont(settings->fontName())); + connect(ui->fcbDefaultFont, &QFontComboBox::currentFontChanged, this, [=](const QFont &f) { + settings->setFontName(f.family()); + }); + connect(settings, &ApplicationSettings::fontNameChanged, this, [=](QString fontName){ + ui->fcbDefaultFont->setCurrentFont(QFont(fontName)); + }); + + ui->spbDefaultFontSize->setValue(settings->fontSize()); + connect(ui->spbDefaultFontSize, QOverload::of(&QSpinBox::valueChanged), settings, &ApplicationSettings::setFontSize); + connect(settings, &ApplicationSettings::fontSizeChanged, ui->spbDefaultFontSize, &QSpinBox::setValue); +} + +PreferencesDialog::~PreferencesDialog() +{ + delete ui; +} + +void PreferencesDialog::showApplicationRestartRequired() const +{ + ui->labelAppRestartIcon->show(); + ui->labelAppRestart->show(); +} + +template +void PreferencesDialog::MapSettingToCheckBox(QCheckBox *checkBox, Func1 getter, Func2 setter, Func3 notifier) const +{ + // Get the value and set the checkbox state + checkBox->setChecked(std::bind(getter, settings)()); + + // Set up two way connection + connect(settings, notifier, checkBox, &QCheckBox::setChecked); + connect(checkBox, &QCheckBox::toggled, settings, setter); +} + +template +void PreferencesDialog::MapSettingToGroupBox(QGroupBox *groupBox, Func1 getter, Func2 setter, Func3 notifier) const +{ + // Get the value and set the checkbox state + groupBox->setChecked(std::bind(getter, settings)()); + + // Set up two way connection + connect(settings, notifier, groupBox, &QGroupBox::setChecked); + connect(groupBox, &QGroupBox::toggled, settings, setter); +} + +void PreferencesDialog::populateTranslationComboBox() +{ + NotepadNextApplication *app = qobject_cast(qApp); + + // Add the system default at the top + ui->comboBoxTranslation->addItem(QStringLiteral("%1 (%2)").arg(tr(""), QLocale::system().name()), QStringLiteral("")); + + // TODO: sort this list and keep the system default at the top + for (const auto &localeName : app->getTranslationManager()->availableTranslations()) + { + QLocale locale(localeName); + const QString localeDisplay = TranslationManager::FormatLocaleTerritoryAndLanguage(locale); + ui->comboBoxTranslation->addItem(QStringLiteral("%1 (%2)").arg(localeDisplay, localeName), localeName); + } + + // Select the current one + int index = ui->comboBoxTranslation->findData(settings->translation()); + if (index != -1) { + ui->comboBoxTranslation->setCurrentIndex(index); + } +} diff --git a/src/NotepadNext/dialogs/PreferencesDialog.h b/src/NotepadNext/dialogs/PreferencesDialog.h new file mode 100644 index 000000000..7593eaa2f --- /dev/null +++ b/src/NotepadNext/dialogs/PreferencesDialog.h @@ -0,0 +1,56 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef PREFERENCESDIALOG_H +#define PREFERENCESDIALOG_H + +#include "ApplicationSettings.h" + +#include +#include +#include + +namespace Ui { +class PreferencesDialog; +} + +class PreferencesDialog : public QDialog +{ + Q_OBJECT + +public: + PreferencesDialog(ApplicationSettings *settings, QWidget *parent = 0); + ~PreferencesDialog(); + + void showApplicationRestartRequired() const; + +private: + Ui::PreferencesDialog *ui; + ApplicationSettings *settings; + + template + void MapSettingToCheckBox(QCheckBox *checkBox, Func1 getter, Func2 setter, Func3 notifier) const; + + template + void MapSettingToGroupBox(QGroupBox *groupBox, Func1 getter, Func2 setter, Func3 notifier) const; + + void populateTranslationComboBox(); +}; + +#endif // PREFERENCESDIALOG_H diff --git a/src/NotepadNext/dialogs/PreferencesDialog.ui b/src/NotepadNext/dialogs/PreferencesDialog.ui new file mode 100644 index 000000000..ce2cadf59 --- /dev/null +++ b/src/NotepadNext/dialogs/PreferencesDialog.ui @@ -0,0 +1,258 @@ + + + PreferencesDialog + + + + 0 + 0 + 838 + 469 + + + + Preferences + + + + + + + + Show menu bar + + + + + + + Show toolbar + + + + + + + Show status bar + + + + + + + Dark Mode + + + + + + + Restore previous session + + + true + + + false + + + + + + Unsaved changes + + + + + + + Temporary files + + + + + + + + + + + + Recenter find/replace dialog when opened + + + + + + + Combine search results + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + Translation: + + + + + + + + + Exit on last tab closed + + + + + + + + + Default Font + + + + + + Font + + + + + + + + + + Font Size + + + + + + + pt + + + 2 + + + 48 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + TextLabel + + + + + + + + true + + + + An application restart is required to apply certain settings. + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + PreferencesDialog + accept() + + + 641 + 439 + + + 157 + 274 + + + + + buttonBox + rejected() + PreferencesDialog + reject() + + + 709 + 439 + + + 286 + 274 + + + + + diff --git a/src/NotepadNext/docks/DebugLogDock.cpp b/src/NotepadNext/docks/DebugLogDock.cpp new file mode 100644 index 000000000..4cb44d745 --- /dev/null +++ b/src/NotepadNext/docks/DebugLogDock.cpp @@ -0,0 +1,52 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "DebugLogDock.h" +#include "ui_DebugLogDock.h" +#include "DebugManager.h" + +#include + +static QPlainTextEdit *output = Q_NULLPTR; + +static void debugLogDockMessageHandler(const QString &msg) +{ + output->appendPlainText(msg); +} + +DebugLogDock::DebugLogDock(QWidget *parent) : + QDockWidget(parent), + ui(new Ui::DebugLogDock) +{ + ui->setupUi(this); + + output = ui->txtDebugOutput; + DebugManager::addMessageHandler(debugLogDockMessageHandler); + + connect(this, &QDockWidget::visibilityChanged, this, [=](bool visible) { + if (visible) { + ui->txtDebugOutput->horizontalScrollBar()->setValue(0); + } + }); +} + +DebugLogDock::~DebugLogDock() +{ + delete ui; +} diff --git a/src/NotepadNext/docks/DebugLogDock.h b/src/NotepadNext/docks/DebugLogDock.h new file mode 100644 index 000000000..6398824fb --- /dev/null +++ b/src/NotepadNext/docks/DebugLogDock.h @@ -0,0 +1,42 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef DEBUGLOGDOCK_H +#define DEBUGLOGDOCK_H + +#include +#include + +namespace Ui { +class DebugLogDock; +} + +class DebugLogDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit DebugLogDock(QWidget *parent = nullptr); + ~DebugLogDock(); + +private: + Ui::DebugLogDock *ui; +}; + +#endif // DEBUGLOGDOCK_H diff --git a/src/NotepadNext/docks/DebugLogDock.ui b/src/NotepadNext/docks/DebugLogDock.ui new file mode 100644 index 000000000..b47a44c9d --- /dev/null +++ b/src/NotepadNext/docks/DebugLogDock.ui @@ -0,0 +1,72 @@ + + + DebugLogDock + + + + 0 + 0 + 400 + 300 + + + + Debug Log + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Courier New + 10 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + QAbstractScrollArea::AdjustToContentsOnFirstShow + + + QPlainTextEdit::NoWrap + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + 1000 + + + + + + + + + diff --git a/src/NotepadNext/docks/EditorInspectorDock.cpp b/src/NotepadNext/docks/EditorInspectorDock.cpp new file mode 100644 index 000000000..cd56753d4 --- /dev/null +++ b/src/NotepadNext/docks/EditorInspectorDock.cpp @@ -0,0 +1,197 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include "EditorInspectorDock.h" +#include "ui_EditorInspectorDock.h" + +#include "MainWindow.h" + + +static inline QString toBool(int b) { + return b ? QStringLiteral("True") : QStringLiteral("False"); +} + +EditorInspectorDock::EditorInspectorDock(MainWindow *parent) : + QDockWidget(parent), + ui(new Ui::EditorInspectorDock) +{ + ui->setupUi(this); + + QTreeWidgetItem *positionInfo = new QTreeWidgetItem(ui->treeWidget); + positionInfo->setText(0, tr("Position Information")); + positionInfo->setExpanded(true); + + newItem(positionInfo, tr("Current Position"), [](ScintillaNext *editor) { return QString::number(editor->currentPos()); }); + newItem(positionInfo, tr("Current Position (x, y)"), [](ScintillaNext *editor) { return QString("(%1, %2)").arg(editor->pointXFromPosition(editor->currentPos())).arg(editor->pointYFromPosition(editor->currentPos())); }); + newItem(positionInfo, tr("Column"), [](ScintillaNext *editor) { return QString::number(editor->column(editor->currentPos())); }); + // SCI_GETCHARAT(position pos) → int + newItem(positionInfo, tr("Current Style"), [](ScintillaNext *editor) { return QString::number(editor->styleAt(editor->currentPos())); }); + newItem(positionInfo, tr("Current Line"), [](ScintillaNext *editor) { return QString::number(editor->lineFromPosition(editor->currentPos()) + 1); }); + newItem(positionInfo, tr("Line Length"), [](ScintillaNext *editor) { return QString::number(editor->lineLength(editor->lineFromPosition(editor->currentPos()))); }); + newItem(positionInfo, tr("Line End Position"), [](ScintillaNext *editor) { return QString::number(editor->lineEndPosition(editor->lineFromPosition(editor->currentPos()))); }); + newItem(positionInfo, tr("Line Indentation"), [](ScintillaNext *editor) { return QString::number(editor->lineIndentation(editor->lineFromPosition(editor->currentPos()))); }); + newItem(positionInfo, tr("Line Indent Position"), [](ScintillaNext *editor) { return QString::number(editor->lineIndentPosition(editor->lineFromPosition(editor->currentPos()))); }); + + + QTreeWidgetItem *selInfo = new QTreeWidgetItem(ui->treeWidget); + selInfo->setText(0, tr("Selection Information")); + selInfo->setExpanded(true); + + newItem(selInfo, tr("Mode"), [](ScintillaNext *editor) { + switch (editor->selectionMode()) { + case SC_SEL_STREAM: + return QStringLiteral("SC_SEL_STREAM"); + case SC_SEL_RECTANGLE: + return QStringLiteral("SC_SEL_RECTANGLE"); + case SC_SEL_LINES: + return QStringLiteral("SC_SEL_LINES"); + case SC_SEL_THIN: + return QStringLiteral("SC_SEL_THIN"); + default: + return QStringLiteral(""); + } + }); + newItem(selInfo, tr("Is Rectangle"), [](ScintillaNext *editor) { return toBool(editor->selectionIsRectangle()); }); + newItem(selInfo, tr("Selection Empty"), [](ScintillaNext *editor) { return toBool(editor->selectionEmpty()); }); + newItem(selInfo, tr("Main Selection"), [](ScintillaNext *editor) { return QString::number(editor->mainSelection()); }); + newItem(selInfo, tr("# of Selections"), [](ScintillaNext *editor) { return QString::number(editor->selections()); }); + + selectionsInfo = new QTreeWidgetItem(selInfo); + selectionsInfo->setText(0, tr("Multiple Selections")); + selectionsInfo->setExpanded(true); + + + QTreeWidgetItem *documentInfo = new QTreeWidgetItem(ui->treeWidget); + documentInfo->setText(0, tr("Document Information")); + documentInfo->setExpanded(true); + + newItem(documentInfo, tr("Length"), [](ScintillaNext *editor) { return QString::number(editor->length()); }); + newItem(documentInfo, tr("Line Count"), [](ScintillaNext *editor) { return QString::number(editor->lineCount()); }); + + + QTreeWidgetItem *viewInfo = new QTreeWidgetItem(ui->treeWidget); + viewInfo->setText(0, tr("View Information")); + viewInfo->setExpanded(true); + + newItem(viewInfo, tr("Lines on Screen"), [](ScintillaNext *editor) { return QString::number(editor->linesOnScreen()); }); + newItem(viewInfo, tr("First Visible Line"), [](ScintillaNext *editor) { return QString::number(editor->firstVisibleLine() + 1); }); + newItem(viewInfo, tr("X Offset"), [](ScintillaNext *editor) { return QString::number(editor->xOffset()); }); + + + QTreeWidgetItem *foldInfo = new QTreeWidgetItem(ui->treeWidget); + foldInfo->setText(0, tr("Fold Information")); + foldInfo->setExpanded(true); + + newItem(foldInfo, tr("Visible From Doc Line"), [](ScintillaNext *editor) { return QString::number(editor->visibleFromDocLine(editor->lineFromPosition(editor->currentPos())) + 1); }); + newItem(foldInfo, tr("Doc Line From Visible"), [](ScintillaNext *editor) { return QString::number(editor->docLineFromVisible(editor->lineFromPosition(editor->currentPos())) + 1); }); + newItem(foldInfo, tr("Fold Level"), [](ScintillaNext *editor) { return QString::number((editor->foldLevel(editor->lineFromPosition(editor->currentPos())) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE); }); + newItem(foldInfo, tr("Is Fold Header"), [](ScintillaNext *editor) { return toBool((editor->foldLevel(editor->lineFromPosition(editor->currentPos())) & SC_FOLDLEVELHEADERFLAG) == SC_FOLDLEVELHEADERFLAG); }); + newItem(foldInfo, tr("Fold Parent"), [](ScintillaNext *editor) { return QString::number(editor->foldParent(editor->lineFromPosition(editor->currentPos())) + 1); }); + newItem(foldInfo, tr("Last Child"), [](ScintillaNext *editor) { return QString::number(editor->lastChild(editor->lineFromPosition(editor->currentPos()), -1) + 1); }); + newItem(foldInfo, tr("Contracted Fold Next"), [](ScintillaNext *editor) { return QString::number(editor->contractedFoldNext(editor->lineFromPosition(editor->currentPos())) + 1); }); + + connect(this, &QDockWidget::visibilityChanged, this, [=](bool visible) { + if (visible) { + connectToEditor(parent->currentEditor()); + connect(parent, &MainWindow::editorActivated, this, &EditorInspectorDock::connectToEditor); + } + else { + disconnectFromEditor(); + disconnect(parent, &MainWindow::editorActivated, this, &EditorInspectorDock::connectToEditor); + } + }); +} + +EditorInspectorDock::~EditorInspectorDock() +{ + delete ui; +} + +void EditorInspectorDock::connectToEditor(ScintillaNext *editor) +{ + disconnectFromEditor(); + + editorConnection = connect(editor, &ScintillaNext::updateUi, this, &EditorInspectorDock::editorUIUpdated); + + updateEditorInfo(editor); +} + + +void EditorInspectorDock::disconnectFromEditor() +{ + if (editorConnection) { + disconnect(editorConnection); + } +} + +void EditorInspectorDock::editorUIUpdated(Scintilla::Update updated) +{ + if (FlagSet(updated, Scintilla::Update::Content) + || FlagSet(updated, Scintilla::Update::Selection) + || FlagSet(updated, Scintilla::Update::VScroll) + || FlagSet(updated, Scintilla::Update::HScroll)) { + ScintillaNext *editor = qobject_cast(sender()); + + updateEditorInfo(editor); + } +} + +void EditorInspectorDock::updateEditorInfo(ScintillaNext *editor) +{ + for (const QPair &pair : qAsConst(items)) { + QTreeWidgetItem *item = pair.first; + + if (item->parent()->isExpanded()) { + EditorFunction func = pair.second; + item->setText(1, func(editor)); + } + } + + qDeleteAll(selectionsInfo->takeChildren()); + + for (int i = 0; i < editor->selections(); ++i) { + QTreeWidgetItem *selection = new QTreeWidgetItem(selectionsInfo); + selection->setText(0, QLatin1Char('#') + QString::number(i)); + selection->setExpanded(true); + + QTreeWidgetItem *caret = new QTreeWidgetItem(selection); + caret->setText(0, tr("Caret")); + caret->setText(1, QString::number(editor->selectionNCaret(i))); + + QTreeWidgetItem *anchor = new QTreeWidgetItem(selection); + anchor->setText(0, tr("Anchor")); + anchor->setText(1, QString::number(editor->selectionNAnchor(i))); + + QTreeWidgetItem *caretVirtual = new QTreeWidgetItem(selection); + caretVirtual->setText(0, tr("Caret Virtual Space")); + caretVirtual->setText(1, QString::number(editor->selectionNCaretVirtualSpace(i))); + + QTreeWidgetItem *anchorVirtual = new QTreeWidgetItem(selection); + anchorVirtual->setText(0, tr("Anchor Virtual Space")); + anchorVirtual->setText(1, QString::number(editor->selectionNAnchorVirtualSpace(i))); + } + + ui->treeWidget->resizeColumnToContents(0); +} + +void EditorInspectorDock::newItem(QTreeWidgetItem *parent, const QString &label, EditorFunction func) +{ + QTreeWidgetItem *item = new QTreeWidgetItem(parent); + item->setText(0, label); + items.append(qMakePair(item, func)); +} diff --git a/src/NotepadNext/docks/EditorInspectorDock.h b/src/NotepadNext/docks/EditorInspectorDock.h new file mode 100644 index 000000000..156e6e056 --- /dev/null +++ b/src/NotepadNext/docks/EditorInspectorDock.h @@ -0,0 +1,61 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef EDITORINSPECTORDOCK_H +#define EDITORINSPECTORDOCK_H + +#include +#include + +#include "ScintillaTypes.h" + + +class MainWindow; +class ScintillaNext; + +typedef std::function EditorFunction; + +namespace Ui { +class EditorInspectorDock; +} + +class EditorInspectorDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit EditorInspectorDock(MainWindow *parent); + ~EditorInspectorDock(); + +private slots: + void connectToEditor(ScintillaNext *editor); + void editorUIUpdated(Scintilla::Update updated); + void updateEditorInfo(ScintillaNext *editor); + +private: + void newItem(QTreeWidgetItem *parent, const QString &label, EditorFunction func); + void disconnectFromEditor(); + + Ui::EditorInspectorDock *ui; + QTreeWidgetItem *selectionsInfo; + QMetaObject::Connection editorConnection; + QVector> items; +}; + +#endif // EDITORINSPECTORDOCK_H diff --git a/src/NotepadNext/docks/EditorInspectorDock.ui b/src/NotepadNext/docks/EditorInspectorDock.ui new file mode 100644 index 000000000..62c82e355 --- /dev/null +++ b/src/NotepadNext/docks/EditorInspectorDock.ui @@ -0,0 +1,58 @@ + + + EditorInspectorDock + + + + 0 + 0 + 284 + 575 + + + + Editor Inspector + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + true + + + true + + + 2 + + + false + + + + 1 + + + + + 2 + + + + + + + + + + diff --git a/src/NotepadNext/docks/FileListDock.cpp b/src/NotepadNext/docks/FileListDock.cpp new file mode 100644 index 000000000..b86a1025c --- /dev/null +++ b/src/NotepadNext/docks/FileListDock.cpp @@ -0,0 +1,208 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "FileListDock.h" +#include "ApplicationSettings.h" +#include "ui_FileListDock.h" + +#include "MainWindow.h" + +ApplicationSetting sortByName{"FileList/SortByName", false}; + +FileListDock::FileListDock(MainWindow *parent) : + QDockWidget(parent), + ui(new Ui::FileList), + window(parent) +{ + qInfo(Q_FUNC_INFO); + + ui->setupUi(this); + ui->btnSettings->addAction(ui->actionSortbyFileName); + + // Set the initial state + ApplicationSettings settings; + ui->actionSortbyFileName->setChecked(settings.get(sortByName)); + + // Track it if it changes + connect(ui->actionSortbyFileName, &QAction::toggled, this, [=](bool b) { + ApplicationSettings settings; + settings.set(sortByName, b); + refreshList(); + }); + + connect(this, &QDockWidget::visibilityChanged, this, [=](bool visible) { + if (visible) { + // Only get events when the dock is visible + connect(window->getDockedEditor(), &DockedEditor::editorAdded, this, [=](ScintillaNext *editor) { + Q_UNUSED(editor); + + // The editor could get added on any DockArea and doesn't necessarily get appended to the end of the FileList, so refresh everything + refreshList(); + }); + connect(window->getDockedEditor(), &DockedEditor::editorActivated, this, &FileListDock::selectCurrentEditor); + connect(window->getDockedEditor(), &DockedEditor::editorClosed, this, &FileListDock::removeEditor); + connect(window->getDockedEditor(), &DockedEditor::editorOrderChanged, this, &FileListDock::refreshList); + + refreshList(); + selectCurrentEditor(); + } + else { + // Disconnect all the editors + for(int i = 0; i < ui->listWidget->count(); ++i) { + QListWidgetItem* item = ui->listWidget->item(i); + const ScintillaNext *other = item->data(Qt::UserRole).value(); + + disconnect(other, Q_NULLPTR, this, Q_NULLPTR); + } + + // Don't need to clear it but why not + ui->listWidget->clear(); + + // Don't need events from the docked editor either + disconnect(window->getDockedEditor(), Q_NULLPTR, this, Q_NULLPTR); + } + }); + + connect(ui->listWidget, &QListWidget::itemClicked, this, &FileListDock::itemClicked); +} + +FileListDock::~FileListDock() +{ + delete ui; +} + +void FileListDock::refreshList() +{ + qInfo(Q_FUNC_INFO); + + ui->listWidget->clear(); + + QVector editors = window->getDockedEditor()->editors(); + ApplicationSettings settings; + + if (settings.get(sortByName)) { + std::sort(editors.begin(), editors.end(), [](const ScintillaNext* e1, const ScintillaNext* e2) { + return QString::compare(e1->getName(), e2->getName(), Qt::CaseInsensitive) < 0; + }); + } + + for (ScintillaNext *editor : editors) { + addEditor(editor); + } + + selectCurrentEditor(); +} + +void FileListDock::addEditor(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + QListWidgetItem *item = new QListWidgetItem(editor->getName()); + item->setToolTip(editor->getName()); + item->setIcon(QIcon(":/icons/saved.png")); + item->setData(Qt::UserRole, QVariant::fromValue(editor)); + item->setIcon(QIcon(editor->canSaveToDisk() ? ":/icons/unsaved.png" : ":/icons/saved.png")); + + // Need some notifications from the editor itself + // NOTE: Cannot use a lambda here because item is not a QObject, and thus cannot be used as a context for Qt to know + // when to cancel the connection. If item was a QObject, the lambda is disconnected when the sender or context is destroyed + connect(editor, &ScintillaNext::savePointChanged, this, &FileListDock::editorSavePointChanged, Qt::UniqueConnection); + connect(editor, &ScintillaNext::renamed, this, &FileListDock::editorRenamed, Qt::UniqueConnection); + + ui->listWidget->addItem(item); +} + +void FileListDock::removeEditor(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + QListWidgetItem* item = lookupItemByEditor(editor); + + if (item) { + delete ui->listWidget->takeItem(ui->listWidget->row(item)); + } +} + +void FileListDock::selectCurrentEditor() +{ + qInfo(Q_FUNC_INFO); + + ScintillaNext *editor = window->currentEditor(); + QListWidgetItem* item = lookupItemByEditor(editor); + + if (item) { + ui->listWidget->setCurrentItem(item); + } +} + +void FileListDock::itemClicked(QListWidgetItem *item) +{ + qInfo(Q_FUNC_INFO); + + ScintillaNext *editor = item->data(Qt::UserRole).value(); + + window->getDockedEditor()->switchToEditor(editor); +} + +void FileListDock::editorSavePointChanged(bool dirty) +{ + Q_UNUSED(dirty); + qInfo(Q_FUNC_INFO); + + ScintillaNext *editor = qobject_cast(sender()); + + if (editor) { + QListWidgetItem* item = lookupItemByEditor(editor); + + if (item) { + const QString iconPath = editor->canSaveToDisk() ? ":/icons/unsaved.png" : ":/icons/saved.png"; + item->setIcon(QIcon(iconPath)); + } + } +} + +void FileListDock::editorRenamed() +{ + qInfo(Q_FUNC_INFO); + + ScintillaNext *editor = qobject_cast(sender()); + + if (editor) { + QListWidgetItem* item = lookupItemByEditor(editor); + + if (item) { + item->setText(editor->getName()); + item->setToolTip(editor->getName()); + } + } +} + +QListWidgetItem *FileListDock::lookupItemByEditor(ScintillaNext *editor) +{ + for(int i = 0; i < ui->listWidget->count(); ++i) { + QListWidgetItem* item = ui->listWidget->item(i); + const ScintillaNext *other = item->data(Qt::UserRole).value(); + + if (other == editor) { + return item; + } + } + + return Q_NULLPTR; +} diff --git a/src/NotepadNext/docks/FileListDock.h b/src/NotepadNext/docks/FileListDock.h new file mode 100644 index 000000000..c86cc6881 --- /dev/null +++ b/src/NotepadNext/docks/FileListDock.h @@ -0,0 +1,61 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef FILELISTDOCK_H +#define FILELISTDOCK_H + +#include "ScintillaNext.h" + +#include +#include + +namespace Ui { +class FileList; +} + +class MainWindow; + +class FileListDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit FileListDock(MainWindow *parent); + ~FileListDock(); + +private slots: + void refreshList(); + void addEditor(ScintillaNext *editor); + void removeEditor(ScintillaNext *editor); + + void selectCurrentEditor(); + + void itemClicked(QListWidgetItem *item); + + void editorSavePointChanged(bool dirty); + void editorRenamed(); + +private: + QListWidgetItem *lookupItemByEditor(ScintillaNext *editor); + + Ui::FileList *ui; + MainWindow *window; +}; + +#endif // FILELISTDOCK_H diff --git a/src/NotepadNext/docks/FileListDock.ui b/src/NotepadNext/docks/FileListDock.ui new file mode 100644 index 000000000..69a7c8ff0 --- /dev/null +++ b/src/NotepadNext/docks/FileListDock.ui @@ -0,0 +1,101 @@ + + + FileList + + + + 0 + 0 + 230 + 508 + + + + File List + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + + :/icons/cog.png:/icons/cog.png + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + Qt::ArrowType::NoArrow + + + + + + + + + QFrame::Shape::NoFrame + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + QAbstractItemView::SelectionBehavior::SelectRows + + + true + + + + + + + + true + + + Sort by File Name + + + QAction::MenuRole::NoRole + + + + + + + + diff --git a/src/NotepadNext/docks/FolderAsWorkspaceDock.cpp b/src/NotepadNext/docks/FolderAsWorkspaceDock.cpp new file mode 100644 index 000000000..f1dd3ed5d --- /dev/null +++ b/src/NotepadNext/docks/FolderAsWorkspaceDock.cpp @@ -0,0 +1,67 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "FolderAsWorkspaceDock.h" +#include "ApplicationSettings.h" +#include "ui_FolderAsWorkspaceDock.h" + +#include + +ApplicationSetting rootPathSetting{"FolderAsWorkspace/RootPath"}; + +FolderAsWorkspaceDock::FolderAsWorkspaceDock(QWidget *parent) : + QDockWidget(parent), + ui(new Ui::FolderAsWorkspaceDock), + model(new QFileSystemModel(this)) +{ + ui->setupUi(this); + + ui->treeView->setModel(model); + ui->treeView->header()->hideSection(1); + ui->treeView->header()->hideSection(2); + ui->treeView->header()->hideSection(3); + + connect(ui->treeView, &QTreeView::doubleClicked, this, [=](const QModelIndex &index) { + if (!model->isDir(index)) { + emit fileDoubleClicked(model->filePath(index)); + } + }); + + ApplicationSettings settings; + setRootPath(settings.get(rootPathSetting)); +} + +FolderAsWorkspaceDock::~FolderAsWorkspaceDock() +{ + delete ui; +} + +void FolderAsWorkspaceDock::setRootPath(const QString dir) +{ + ApplicationSettings settings; + settings.set(rootPathSetting, dir); + + model->setRootPath(dir); + ui->treeView->setRootIndex(model->index(dir)); +} + +QString FolderAsWorkspaceDock::rootPath() const +{ + return model->rootPath(); +} diff --git a/src/NotepadNext/docks/FolderAsWorkspaceDock.h b/src/NotepadNext/docks/FolderAsWorkspaceDock.h new file mode 100644 index 000000000..085254905 --- /dev/null +++ b/src/NotepadNext/docks/FolderAsWorkspaceDock.h @@ -0,0 +1,51 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef FOLDERASWORKSPACEDOCK_H +#define FOLDERASWORKSPACEDOCK_H + +#include + +namespace Ui { +class FolderAsWorkspaceDock; +} + +class QFileSystemModel; + +class FolderAsWorkspaceDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit FolderAsWorkspaceDock(QWidget *parent = nullptr); + ~FolderAsWorkspaceDock(); + + void setRootPath(const QString dir); + QString rootPath() const; + +signals: + void fileDoubleClicked(const QString &filePath); + +private: + Ui::FolderAsWorkspaceDock *ui; + + QFileSystemModel *model; +}; + +#endif // FOLDERASWORKSPACEDOCK_H diff --git a/src/NotepadNext/docks/FolderAsWorkspaceDock.ui b/src/NotepadNext/docks/FolderAsWorkspaceDock.ui new file mode 100644 index 000000000..3515d5620 --- /dev/null +++ b/src/NotepadNext/docks/FolderAsWorkspaceDock.ui @@ -0,0 +1,45 @@ + + + FolderAsWorkspaceDock + + + + 0 + 0 + 293 + 575 + + + + Folder as Workspace + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + false + + + + + + + + + diff --git a/src/NotepadNext/docks/HexViewerDock.cpp b/src/NotepadNext/docks/HexViewerDock.cpp new file mode 100644 index 000000000..cb0213d8b --- /dev/null +++ b/src/NotepadNext/docks/HexViewerDock.cpp @@ -0,0 +1,68 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include + +#include "MainWindow.h" +#include "ScintillaNext.h" + +#include "HexViewerDock.h" +#include "ui_HexViewerDock.h" + +#include "EditorHexViewerTableModel.h" + + +HexViewerDock::HexViewerDock(MainWindow *parent) : + QDockWidget(parent), + ui(new Ui::HexViewerDock) +{ + ui->setupUi(this); + + // Set the font of the table to a monospaced font...not sure how best to do this + QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont).family(); + ui->tblHexView->setFont(font); + + connect(this, &QDockWidget::visibilityChanged, this, [=](bool visible) { + if (visible) { + connectToEditor(parent->currentEditor()); + + connect(parent, &MainWindow::editorActivated, this, &HexViewerDock::connectToEditor); + } + else { + disconnect(parent, &MainWindow::editorActivated, this, &HexViewerDock::connectToEditor); + } + }); +} + +HexViewerDock::~HexViewerDock() +{ + delete ui; +} + +void HexViewerDock::connectToEditor(ScintillaNext *editor) +{ + if (auto model = ui->tblHexView->model()) { + model->deleteLater(); + } + + EditorHexViewerTableModel *model = new EditorHexViewerTableModel(this); + model->setEditor(editor); + ui->tblHexView->setModel(model); + ui->tblHexView->resizeColumnsToContents(); + ui->tblHexView->resizeRowsToContents(); +} diff --git a/src/NotepadNext/docks/HexViewerDock.h b/src/NotepadNext/docks/HexViewerDock.h new file mode 100644 index 000000000..718225c2b --- /dev/null +++ b/src/NotepadNext/docks/HexViewerDock.h @@ -0,0 +1,47 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef HEXVIEWERDOCK_H +#define HEXVIEWERDOCK_H + +#include + +namespace Ui { +class HexViewerDock; +} +class MainWindow; +class ScintillaNext; + +class HexViewerDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit HexViewerDock(MainWindow *parent); + ~HexViewerDock(); + +private slots: + void connectToEditor(ScintillaNext *editor); + +private: + + Ui::HexViewerDock *ui; +}; + +#endif // HEXVIEWERDOCK_H diff --git a/src/NotepadNext/docks/HexViewerDock.ui b/src/NotepadNext/docks/HexViewerDock.ui new file mode 100644 index 000000000..a42cdba3d --- /dev/null +++ b/src/NotepadNext/docks/HexViewerDock.ui @@ -0,0 +1,78 @@ + + + HexViewerDock + + + + 0 + 0 + 400 + 300 + + + + Hex Viewer + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + QAbstractItemView::DoubleClicked + + + false + + + false + + + false + + + QAbstractItemView::NoSelection + + + Qt::ElideNone + + + QAbstractItemView::ScrollPerItem + + + QAbstractItemView::ScrollPerPixel + + + Qt::SolidLine + + + false + + + false + + + + + + + + + diff --git a/src/NotepadNext/docks/LanguageInspectorDock.cpp b/src/NotepadNext/docks/LanguageInspectorDock.cpp new file mode 100644 index 000000000..6e945704a --- /dev/null +++ b/src/NotepadNext/docks/LanguageInspectorDock.cpp @@ -0,0 +1,270 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#include + +#include "LanguageInspectorDock.h" +#include "ui_LanguageInspectorDock.h" + +#include "MainWindow.h" +#include "LanguageStylesModel.h" + +#include "SpinBoxDelegate.h" +#include "ColorPickerDelegate.h" +#include "ComboBoxDelegate.h" + +#include "ScintillaNext.h" + +static QSpinBox *FontSizeSpinBoxFactory() +{ + QSpinBox *editor = new QSpinBox(); + editor->setFrame(false); + editor->setRange(2, 24); + editor->setAlignment(Qt::AlignHCenter); + return editor; +} + +static QSpinBox *FontWeightSpinBoxFactory() +{ + QSpinBox *editor = new QSpinBox(); + editor->setFrame(false); + editor->setRange(100, 2400); + editor->setSingleStep(10); + editor->setAlignment(Qt::AlignHCenter); + return editor; +} + +static QString property_type_to_string(int type) { + switch (type) { + case SC_TYPE_BOOLEAN: + return "Bool"; + case SC_TYPE_INTEGER: + return "Int"; + case SC_TYPE_STRING: + return "String"; + default: + return "unknown"; + } +} + +LanguageInspectorDock::LanguageInspectorDock(MainWindow *parent) : + QDockWidget(parent), + ui(new Ui::LanguageInspectorDock) +{ + ui->setupUi(this); + + SpinBoxDelegate *fontSizeDelegate = new SpinBoxDelegate(FontSizeSpinBoxFactory, this); + ui->tblStyles->setItemDelegateForColumn(5, fontSizeDelegate); + + SpinBoxDelegate *fontWeightDelegate = new SpinBoxDelegate(FontWeightSpinBoxFactory, this); + ui->tblStyles->setItemDelegateForColumn(6, fontWeightDelegate); + + ColorPickerDelegate *foreColorDelegate = new ColorPickerDelegate(this); + ui->tblStyles->setItemDelegateForColumn(11, foreColorDelegate); + + ColorPickerDelegate *backColorDelegate = new ColorPickerDelegate(this); + ui->tblStyles->setItemDelegateForColumn(12, backColorDelegate); + + QList caseItems{ + {"SC_CASE_MIXED", SC_CASE_MIXED}, + {"SC_CASE_UPPER", SC_CASE_UPPER}, + {"SC_CASE_LOWER", SC_CASE_LOWER}, + {"SC_CASE_CAMEL", SC_CASE_CAMEL} + }; + ComboBoxDelegate *caseComoboDelegate = new ComboBoxDelegate(caseItems, this); + ui->tblStyles->setItemDelegateForColumn(15, caseComoboDelegate); + + QList fontNames; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + for (const QString &font : QFontDatabase::families()) { +#else + QFontDatabase fontDatabase; + for (const QString &font : fontDatabase.families()) { +#endif + fontNames.append(QPair(font, font)); + } + ComboBoxDelegate *fontComboDelegate = new ComboBoxDelegate(fontNames, this); + ui->tblStyles->setItemDelegateForColumn(4, fontComboDelegate); + + connect(this, &QDockWidget::visibilityChanged, this, [=](bool visible) { + if (visible) { + connectToEditor(parent->currentEditor()); + connect(parent, &MainWindow::editorActivated, this, &LanguageInspectorDock::connectToEditor); + } + else { + disconnectFromEditor(); + disconnect(parent, &MainWindow::editorActivated, this, &LanguageInspectorDock::connectToEditor); + } + }); +} + +LanguageInspectorDock::~LanguageInspectorDock() +{ + delete ui; +} + +void LanguageInspectorDock::connectToEditor(ScintillaNext *editor) +{ + disconnectFromEditor(); + + editorConnection = connect(editor, &ScintillaNext::updateUi, this, &LanguageInspectorDock::updatePositionInfo); + documentConnection = connect(editor, &ScintillaNext::lexerChanged, this, [=]() { updateLexerInfo(editor); }); + + updateLexerInfo(editor); +} + +void LanguageInspectorDock::disconnectFromEditor() +{ + if (editorConnection) { + disconnect(editorConnection); + } + + if (documentConnection) { + disconnect(documentConnection); + } +} + +void LanguageInspectorDock::updatePositionInfo(Scintilla::Update updated) +{ + if (FlagSet(updated, Scintilla::Update::Content) || FlagSet(updated, Scintilla::Update::Selection)) { + ScintillaNext *editor = qobject_cast(sender()); + ui->lblInfo->setText(tr("Position %1 Style %2").arg(editor->currentPos()).arg(editor->styleAt(editor->currentPos()))); + } +} + +void LanguageInspectorDock::updateLexerInfo(ScintillaNext *editor) +{ + updateLanguageName(editor); + updatePropertyInfo(editor); + updateKeywordInfo(editor); + updateStyleInfo(editor); +} + +void LanguageInspectorDock::updateLanguageName(ScintillaNext *editor) +{ + qInfo(Q_FUNC_INFO); + + ui->editLanguage->setText(editor->languageName); + ui->editLexer->setText(editor->lexerLanguage()); +} + +void LanguageInspectorDock::updatePropertyInfo(ScintillaNext *editor) +{ + const QSignalBlocker blocker(ui->tblProperties); + + ui->tblProperties->clearContents(); + + const QString propertyNames = editor->propertyNames(); + + if (propertyNames.isEmpty()) { + ui->tblProperties->setRowCount(0); + } + else { + QStringList propertyNamesList = propertyNames.split('\n'); + + ui->tblProperties->setRowCount(propertyNamesList.count()); + + for (int i = 0; i < propertyNamesList.count(); ++i) { + const auto property = propertyNamesList[i]; + + QTableWidgetItem *prop = new QTableWidgetItem(property); + QTableWidgetItem *type = new QTableWidgetItem(property_type_to_string(editor->propertyType(property.toLatin1().constData()))); + QTableWidgetItem *desc = new QTableWidgetItem(QString(editor->describeProperty(property.toLatin1().constData()))); + QTableWidgetItem *val = new QTableWidgetItem(QString(editor->property(property.toLatin1().constData()))); + + desc->setToolTip(desc->text()); + + prop->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + type->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + desc->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + val->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + + val->setTextAlignment(Qt::AlignCenter); + + ui->tblProperties->setItem(i, 0, prop); + ui->tblProperties->setItem(i, 1, type); + ui->tblProperties->setItem(i, 2, desc); + ui->tblProperties->setItem(i, 3, val); + } + } + + ui->tblProperties->resizeColumnToContents(0); + ui->tblProperties->resizeColumnToContents(1); + ui->tblProperties->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); + ui->tblProperties->resizeColumnToContents(3); + + ui->tblProperties->disconnect(); + connect(ui->tblProperties, &QTableWidget::itemChanged, this, [=](QTableWidgetItem *item) { + const QString property = ui->tblProperties->item(item->row(), 0)->text(); + + editor->setProperty(property.toLatin1().constData(), item->text().toLatin1().constData()); + + editor->colourise(0, -1); + }); +} + +void LanguageInspectorDock::updateKeywordInfo(ScintillaNext *editor) +{ + ui->tblKeywords->clearContents(); + + const QString keyWordSetsDescription = QString(editor->describeKeyWordSets()); + + if (keyWordSetsDescription.isEmpty()) { + ui->tblKeywords->setRowCount(0); + } + else { + QStringList keyWordsSets = keyWordSetsDescription.split('\n'); + + ui->tblKeywords->setRowCount(keyWordsSets.count()); + + for (int i = 0; i < keyWordsSets.count(); ++i) { + auto id = new QTableWidgetItem(QString::number(i)); + id->setTextAlignment(Qt::AlignCenter); + + ui->tblKeywords->setItem(i, 0, id); + ui->tblKeywords->setItem(i, 1, new QTableWidgetItem(keyWordsSets[i])); + } + } + + ui->tblKeywords->resizeColumnToContents(0); +} + +void LanguageInspectorDock::updateStyleInfo(ScintillaNext *editor) +{ + if (auto model = ui->tblStyles->model()) { + model->deleteLater(); + } + ui->tblStyles->setModel(new LanguageStylesModel(editor)); + + ui->tblStyles->resizeColumnToContents(0); + ui->tblStyles->resizeColumnToContents(1); + ui->tblStyles->resizeColumnToContents(5); + ui->tblStyles->resizeColumnToContents(6); + ui->tblStyles->resizeColumnToContents(7); + ui->tblStyles->resizeColumnToContents(8); + ui->tblStyles->resizeColumnToContents(9); + ui->tblStyles->resizeColumnToContents(10); + ui->tblStyles->resizeColumnToContents(11); + ui->tblStyles->resizeColumnToContents(12); + ui->tblStyles->resizeColumnToContents(13); + ui->tblStyles->resizeColumnToContents(14); + ui->tblStyles->resizeColumnToContents(15); + ui->tblStyles->resizeColumnToContents(16); + ui->tblStyles->resizeColumnToContents(17); + ui->tblStyles->resizeColumnToContents(18); +} diff --git a/src/NotepadNext/docks/LanguageInspectorDock.h b/src/NotepadNext/docks/LanguageInspectorDock.h new file mode 100644 index 000000000..3d1e4b91b --- /dev/null +++ b/src/NotepadNext/docks/LanguageInspectorDock.h @@ -0,0 +1,59 @@ +/* + * This file is part of Notepad Next. + * Copyright 2021 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + +#ifndef LANGUAGEINSPECTORDOCK_H +#define LANGUAGEINSPECTORDOCK_H + +#include + +#include "ScintillaTypes.h" + +class MainWindow; +class ScintillaNext; + +namespace Ui { +class LanguageInspectorDock; +} + +class LanguageInspectorDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit LanguageInspectorDock(MainWindow *parent); + ~LanguageInspectorDock(); + +private slots: + void connectToEditor(ScintillaNext *editor); + void updatePositionInfo(Scintilla::Update updated); + void updateLexerInfo(ScintillaNext *editor); + +private: + Ui::LanguageInspectorDock *ui; + + QMetaObject::Connection editorConnection; + QMetaObject::Connection documentConnection; + + void disconnectFromEditor(); + void updateLanguageName(ScintillaNext *editor); + void updatePropertyInfo(ScintillaNext *editor); + void updateKeywordInfo(ScintillaNext *editor); + void updateStyleInfo(ScintillaNext *editor); +}; + +#endif // LANGUAGEINSPECTORDOCK_H diff --git a/src/NotepadNext/docks/LanguageInspectorDock.ui b/src/NotepadNext/docks/LanguageInspectorDock.ui new file mode 100644 index 000000000..16db25e31 --- /dev/null +++ b/src/NotepadNext/docks/LanguageInspectorDock.ui @@ -0,0 +1,186 @@ + + + LanguageInspectorDock + + + + 0 + 0 + 613 + 566 + + + + Language Inspector + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + true + + + + + 0 + 0 + 611 + 540 + + + + + + + + + Language: + + + + + + + true + + + + + + + Lexer: + + + + + + + true + + + + + + + + + Properties: + + + + + + + false + + + false + + + + Property + + + + + Type + + + + + Description + + + + + Value + + + + + + + + Keywords: + + + + + + + QAbstractItemView::NoEditTriggers + + + 2 + + + false + + + true + + + false + + + + ID + + + + + Description + + + + + + + + Styles: + + + + + + + TextLabel + + + + + + + false + + + + + + + + + + + + + diff --git a/src/NotepadNext/docks/LuaConsoleDock.cpp b/src/NotepadNext/docks/LuaConsoleDock.cpp new file mode 100644 index 000000000..55dde19ed --- /dev/null +++ b/src/NotepadNext/docks/LuaConsoleDock.cpp @@ -0,0 +1,401 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "LuaConsoleDock.h" +#include "ui_LuaConsoleDock.h" + +#include "ScintillaNext.h" +#include "ILexer.h" +#include "Lexilla.h" +#include "SciLexer.h" +#include "MainWindow.h" + +#include "LuaState.h" + +#include "lua.hpp" + +#include "LuaExtension.h" + +#include "ThemeColors.h" + +#include +#include + +#define INDIC_BRACEHIGHLIGHT INDIC_CONTAINER + +static bool inline isBrace(int ch) { + return strchr("[]{}()", ch) != NULL; +} + +inline static void raise_error(lua_State *L, const char *errMsg=NULL) { + luaL_where(L, 1); + if (errMsg) { + lua_pushstring(L, errMsg); + } else { + lua_insert(L, -2); + } + lua_concat(L, 2); + lua_error(L); +} + +static int cf_global_print(lua_State *L) { + LuaConsoleDock *dock = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + int nargs = lua_gettop(L); + + lua_getglobal(L, "tostring"); + + for (int i = 1; i <= nargs; ++i) { + if (i > 1) + dock->writeToOutput("\t"); + + const char *argStr = lua_tostring(L, i); + if (argStr) { + dock->writeToOutput(argStr); + } else { + lua_pushvalue(L, -1); // tostring + lua_pushvalue(L, i); + lua_call(L, 1, 1); + argStr = lua_tostring(L, -1); + if (argStr) { + dock->writeToOutput(argStr); + } else { + raise_error(L, "tostring (called from print) returned a non-string"); + } + lua_settop(L, nargs + 1); + } + } + + dock->writeToOutput("\r\n"); + return 0; +} + + +LuaConsoleDock::LuaConsoleDock(LuaState *l, QWidget *parent) : + QDockWidget(parent), + ui(new Ui::LuaConsoleDock) +{ + L = l; + darkMode = ((MainWindow*)parent)->getSettings()->darkMode(); + + // Override print to print to the console + lua_pushlightuserdata(L->L, this); + lua_pushcclosure(L->L, cf_global_print, 1); + lua_setglobal(L->L, "print"); + + ui->setupUi(this); + + output = new ScintillaNext(Q_NULLPTR, this); + + QFrame *line; + line = new QFrame(this); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + input = new ScintillaNext(Q_NULLPTR, this); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(output); + layout->addWidget(line); + layout->addWidget(input); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + QWidget *widget = new QWidget(this); + widget->setLayout(layout); + setWidget(widget); + + output->setUndoCollection(false); + output->setReadOnly(true); + output->setILexer(reinterpret_cast(CreateLexer("lua"))); + output->usePopUp(SC_POPUP_NEVER); + output->setMarginWidthN(1, output->textWidth(STYLE_DEFAULT, ">") * 2); + output->setMarginTypeN(1, SC_MARGIN_RTEXT); + output->styleSetBold(STYLE_LINENUMBER, true); + output->setScrollWidth(1); + + // Have it actually do the lexing + input->setILexer(reinterpret_cast(CreateLexer("lua"))); + + // Setup Keywords + input->setKeyWords(0, "and break do else elseif end false for function goto if in local nil not or repeat return then true until while"); + input->setKeyWords(1, "_ENV _G _VERSION assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawlen rawset require select setfenv setmetatable tonumber tostring type unpack xpcall string table math bit32 coroutine io os debug package __index __newindex __call __add __sub __mul __div __mod __pow __unm __concat __len __eq __lt __le __gc __mode"); + input->setKeyWords(2, "byte char dump find format gmatch gsub len lower rep reverse sub upper abs acos asin atan atan2 ceil cos cosh deg exp floor fmod frexp ldexp log log10 max min modf pow rad random randomseed sin sinh sqrt tan tanh arshift band bnot bor btest bxor extract lrotate lshift replace rrotate rshift shift string.byte string.char string.dump string.find string.format string.gmatch string.gsub string.len string.lower string.match string.rep string.reverse string.sub string.upper table.concat table.insert table.maxn table.pack table.remove table.sort table.unpack math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.cosh math.deg math.exp math.floor math.fmod math.frexp math.huge math.ldexp math.log math.log10 math.max math.min math.modf math.pi math.pow math.rad math.random math.randomseed math.sin math.sinh math.sqrt math.tan math.tanh bit32.arshift bit32.band bit32.bnot bit32.bor bit32.btest bit32.bxor bit32.extract bit32.lrotate bit32.lshift bit32.replace bit32.rrotate bit32.rshift"); + input->setKeyWords(3, "close flush lines read seek setvbuf write clock date difftime execute exit getenv remove rename setlocale time tmpname coroutine.create coroutine.resume coroutine.running coroutine.status coroutine.wrap coroutine.yield io.close io.flush io.input io.lines io.open io.output io.popen io.read io.tmpfile io.type io.write io.stderr io.stdin io.stdout os.clock os.date os.difftime os.execute os.exit os.getenv os.remove os.rename os.setlocale os.time os.tmpname debug.debug debug.getfenv debug.gethook debug.getinfo debug.getlocal debug.getmetatable debug.getregistry debug.getupvalue debug.getuservalue debug.setfenv debug.sethook debug.setlocal debug.setmetatable debug.setupvalue debug.setuservalue debug.traceback debug.upvalueid debug.upvaluejoin package.cpath package.loaded package.loaders package.loadlib package.path package.preload package.seeall"); + + // Highlight constants + //input->setKeyWords(4, join(SciIFaceTable.GetAllConstantNames(), ' ').c_str()); + //input->setKeyWords(5, join(NppIFaceTable.GetAllConstantNames(), ' ').c_str()); + + // Set up some autocomplete junk + input->autoCSetIgnoreCase(true); + input->autoCSetMaxHeight(8); + input->autoCSetCancelAtStart(false); + + input->indicSetStyle(INDIC_BRACEHIGHLIGHT, INDIC_STRAIGHTBOX); + input->indicSetUnder(INDIC_BRACEHIGHLIGHT, true); + input->braceHighlightIndicator(true, INDIC_BRACEHIGHLIGHT); + + input->setIndentationGuides(SC_IV_LOOKBOTH); + + input->setHScrollBar(false); + input->setMarginWidthN(1, input->textWidth(STYLE_DEFAULT, ">") * 2); + input->setMarginTypeN(1, SC_MARGIN_RTEXT); + input->styleSetBold(STYLE_LINENUMBER, true); + input->setMarginLeft(2); + if (darkMode) + input->setCaretFore(DARK_DEFAULT_FG); + + input->clearCmdKey('Q' + (SCMOD_CTRL << 16)); + input->clearCmdKey('W' + (SCMOD_CTRL << 16)); + input->clearCmdKey('E' + (SCMOD_CTRL << 16)); + input->clearCmdKey('R' + (SCMOD_CTRL << 16)); + input->clearCmdKey('T' + (SCMOD_CTRL << 16)); + input->clearCmdKey('O' + (SCMOD_CTRL << 16)); + input->clearCmdKey('P' + (SCMOD_CTRL << 16)); + + input->clearCmdKey('S' + (SCMOD_CTRL << 16)); + input->clearCmdKey('D' + (SCMOD_CTRL << 16)); + input->clearCmdKey('F' + (SCMOD_CTRL << 16)); + input->clearCmdKey('G' + (SCMOD_CTRL << 16)); + input->clearCmdKey('H' + (SCMOD_CTRL << 16)); + input->clearCmdKey('J' + (SCMOD_CTRL << 16)); + input->clearCmdKey('K' + (SCMOD_CTRL << 16)); + input->clearCmdKey('L' + (SCMOD_CTRL << 16)); + input->clearCmdKey('B' + (SCMOD_CTRL << 16)); + input->clearCmdKey('N' + (SCMOD_CTRL << 16)); + input->clearCmdKey('M' + (SCMOD_CTRL << 16)); + + input->clearCmdKey(SCK_RETURN); // don't allow normal new lines + + input->marginSetText(0, ">"); + input->marginSetStyle(0, STYLE_LINENUMBER); + + setupStyle(input); + setupStyle(output); + + output->styleSetFore(39, 0x0000FF); // For error messages + + int minHeight = input->textHeight(0); + if(darkMode) minHeight *= 2; // double height for dark mode, smaller in dark + + input->setExtraAscent(2); + input->setExtraDescent(2); + input->setMaximumHeight(minHeight); + input->installEventFilter(this); + + connect(input, &ScintillaNext::updateUi, [=](Scintilla::Update flags) { + Q_UNUSED(flags); + int curPos = input->currentPos(); + int bracePos = INVALID_POSITION; + + // Check on both sides + if (isBrace(input->charAt(curPos - 1))) { + bracePos = curPos - 1; + } + else if (isBrace(input->charAt(curPos))) { + bracePos = curPos; + } + + // See if we are next to a brace + if (bracePos != INVALID_POSITION) { + int otherPos = input->braceMatch(bracePos, 0); + if (otherPos != INVALID_POSITION) { + input->braceHighlight(bracePos, otherPos); + } + else { + input->braceHighlight(INVALID_POSITION, INVALID_POSITION); + } + } + else { + input->braceHighlight(INVALID_POSITION, INVALID_POSITION); + } + }); + + connect(input, &ScintillaNext::linesAdded, [=](int linesAdded) { + if (input->lineCount() > 0) + qInfo("lines added %d", linesAdded); + }); +} + +LuaConsoleDock::~LuaConsoleDock() +{ + delete ui; +} + +void LuaConsoleDock::writeToOutput(const char *s) +{ + output->setReadOnly(false); + output->appendText(strlen(s), s); + output->setReadOnly(true); + output->documentEnd(); +} + +void LuaConsoleDock::writeErrorToOutput(const char *s) +{ + typedef struct { + unsigned char c; + unsigned char style; + } cell; + + const int length = static_cast(strlen(s)); + QVector cells(length + 1); + + for (auto i = 0; i < length; ++i) { + cells[i].c = s[i]; + cells[i].style = 39; + } + + cells[length].c = 0; + cells[length].style = 0; + + output->setReadOnly(false); + output->documentEnd(); + output->addStyledText(length * 2, (const char *) cells.constData()); + output->setReadOnly(true); + output->documentEnd(); +} + +void LuaConsoleDock::runCurrentCommand() +{ + int prevLastLine = output->lineCount(); + int newLastLine = 0; + + Sci_TextRange tr; + tr.chrg.cpMin = 0; + tr.chrg.cpMax = input->length(); + tr.lpstrText = new char[2 * (tr.chrg.cpMax - tr.chrg.cpMin) + 2]; // See documentation + input->send(SCI_GETSTYLEDTEXT, 0, (sptr_t) &tr); + + output->documentEnd(); + output->setReadOnly(false); + output->addStyledText(2 * (tr.chrg.cpMax - tr.chrg.cpMin), tr.lpstrText); + + writeToOutput("\r\n"); + + delete[] tr.lpstrText; + + newLastLine = output->lineCount(); + + for (int i = prevLastLine; i < newLastLine; ++i) { + output->marginSetText(i - 1, ">"); + output->marginSetStyle(i - 1, STYLE_LINENUMBER); + } + + QString text((const char *)input->characterPointer()); + //historyAdd(GUI::StringFromUTF8(text).c_str()); + + input->clearAll(); + input->emptyUndoBuffer(); + input->marginSetText(0, ">"); + input->marginSetStyle(0, STYLE_LINENUMBER); + + LuaExtension::Instance().OnExecute(text.toLatin1().constData()); +} + +bool LuaConsoleDock::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Return && keyEvent->modifiers() == Qt::NoModifier) { + runCurrentCommand(); + return true; + } + } + else { + // standard event processing + return QObject::eventFilter(obj, event); + } + return false; +} + +void LuaConsoleDock::setupStyle(ScintillaNext *editor) +{ + editor->setEOLMode(SC_EOL_CRLF); + + int defaultFg = darkMode ? DARK_DEFAULT_FG : LIGHT_DEFAULT_FG; + int defaultBg = darkMode ? DARK_DEFAULT_BG : LIGHT_DEFAULT_BG; + + editor->styleSetFont(STYLE_DEFAULT, "Courier New"); + editor->styleSetSize(STYLE_DEFAULT, 11); // 10 too small on MacOS at least + editor->styleSetFore(STYLE_DEFAULT, defaultFg); + editor->styleSetBack(STYLE_DEFAULT, defaultBg); + editor->styleClearAll(); + + // Setup the margins + int margin = 0; + editor->setMarginWidthN(0, margin); + editor->setMarginWidthN(2, margin); + editor->setMarginWidthN(3, margin); + editor->setMarginWidthN(4, margin); + + editor->setCodePage(SC_CP_UTF8); + editor->styleSetBold(SCE_LUA_WORD, 1); // for SCI_SETKEYWORDS, 0 + editor->styleSetBold(SCE_LUA_OPERATOR, 1); + editor->styleSetBold(SCE_LUA_WORD2, 1); // for SCI_SETKEYWORDS, 1 + editor->styleSetBold(SCE_LUA_WORD3, 1); // for SCI_SETKEYWORDS, 2 + editor->styleSetBold(SCE_LUA_WORD4, 1); + editor->styleSetItalic(SCE_LUA_WORD4, 1); // for SCI_SETKEYWORDS, 3 + editor->styleSetBold(SCE_LUA_LABEL, 1); + editor->styleSetBold(SCE_LUA_WORD5, 1); + editor->styleSetBold(SCE_LUA_WORD6, 1); + + if(darkMode){ + // set back ground color, default + for(int i = SCE_LUA_DEFAULT; i <= SCE_LUA_LABEL; i++){ + editor->styleSetFore(i, defaultFg); + editor->styleSetBack(i, DARK_DEFAULT_BG); + } + + int commentColor = 0x808000; + editor->styleSetFore(SCE_LUA_COMMENT, commentColor); + editor->styleSetFore(SCE_LUA_COMMENTLINE, commentColor); + editor->styleSetFore(SCE_LUA_COMMENTDOC, commentColor); + editor->styleSetFore(SCE_LUA_LITERALSTRING, 0x4A0095); + editor->styleSetFore(SCE_LUA_PREPROCESSOR, 0x004080); // Technically not used since this is lua 5+ + editor->styleSetFore(SCE_LUA_WORD, 0xFF0000); + editor->styleSetFore(SCE_LUA_NUMBER, 0x0080FF); + editor->styleSetFore(SCE_LUA_STRING, 0x808080); + editor->styleSetFore(SCE_LUA_CHARACTER, 0x808080); + editor->styleSetFore(SCE_LUA_OPERATOR, 0x800000); + editor->styleSetFore(SCE_LUA_WORD2, 0xC08000); + editor->styleSetFore(SCE_LUA_WORD3, 0xFF0080); + editor->styleSetFore(SCE_LUA_WORD4, DARK_DEFAULT_FG); + editor->styleSetFore(SCE_LUA_LABEL, 0x008080); + editor->styleSetFore(SCE_LUA_WORD5, 0x004080); // for SCI_SETKEYWORDS, 4, Scintilla defines + editor->styleSetFore(SCE_LUA_WORD6, 0x004080); // for SCI_SETKEYWORDS, 5, Notepad++ defines + } + else { + editor->styleSetFore(SCE_LUA_COMMENT, 0x008000); + editor->styleSetFore(SCE_LUA_COMMENTLINE, 0x008000); + editor->styleSetFore(SCE_LUA_COMMENTDOC, 0x808000); + editor->styleSetFore(SCE_LUA_LITERALSTRING, 0x4A0095); + editor->styleSetFore(SCE_LUA_PREPROCESSOR, 0x004080); // Technically not used since this is lua 5+ + editor->styleSetFore(SCE_LUA_WORD, 0xFF0000); + editor->styleSetFore(SCE_LUA_NUMBER, 0x0080FF); + editor->styleSetFore(SCE_LUA_STRING, 0x808080); + editor->styleSetFore(SCE_LUA_CHARACTER, 0x808080); + editor->styleSetFore(SCE_LUA_OPERATOR, 0x800000); + editor->styleSetFore(SCE_LUA_WORD2, 0xC08000); + editor->styleSetFore(SCE_LUA_WORD3, 0xFF0080); + editor->styleSetFore(SCE_LUA_WORD4, 0x000000); + editor->styleSetFore(SCE_LUA_LABEL, 0x008080); + editor->styleSetFore(SCE_LUA_WORD5, 0x004080); // for SCI_SETKEYWORDS, 4, Scintilla defines + editor->styleSetFore(SCE_LUA_WORD6, 0x004080); // for SCI_SETKEYWORDS, 5, Notepad++ defines + } +} diff --git a/src/NotepadNext/docks/LuaConsoleDock.h b/src/NotepadNext/docks/LuaConsoleDock.h new file mode 100644 index 000000000..13e8b3150 --- /dev/null +++ b/src/NotepadNext/docks/LuaConsoleDock.h @@ -0,0 +1,62 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef LUACONSOLEDOCK_H +#define LUACONSOLEDOCK_H + +#include + +class ScintillaNext; +class LuaState; + +namespace Ui { +class LuaConsoleDock; +} + +class LuaConsoleDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit LuaConsoleDock(LuaState *l, QWidget *parent = 0); + ~LuaConsoleDock(); + + void writeToOutput(const char *s); + void writeErrorToOutput(const char *s); + LuaState *L = Q_NULLPTR; + +public slots: + void runCurrentCommand(void); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +private: + Ui::LuaConsoleDock *ui; + + ScintillaNext *output; + ScintillaNext *input; + + bool darkMode = false; + + + void setupStyle(ScintillaNext *editor); +}; + +#endif // LUACONSOLEDOCK_H diff --git a/src/NotepadNext/docks/LuaConsoleDock.ui b/src/NotepadNext/docks/LuaConsoleDock.ui new file mode 100644 index 000000000..1944414fa --- /dev/null +++ b/src/NotepadNext/docks/LuaConsoleDock.ui @@ -0,0 +1,22 @@ + + + LuaConsoleDock + + + + 0 + 0 + 400 + 300 + + + + Qt::BottomDockWidgetArea|Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea + + + Lua Console + + + + + diff --git a/src/NotepadNext/docks/SearchResultsDock.cpp b/src/NotepadNext/docks/SearchResultsDock.cpp new file mode 100644 index 000000000..08bacd8a0 --- /dev/null +++ b/src/NotepadNext/docks/SearchResultsDock.cpp @@ -0,0 +1,229 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#include "SearchResultsDock.h" +#include "ScintillaNext.h" +#include "ui_SearchResultsDock.h" + +#include +#include +#include +#include +#include + +enum SearchResultData +{ + LineNumber = Qt::UserRole, + LinePosStart, + LinePosEnd +}; + +SearchResultsDock::SearchResultsDock(QWidget *parent) : + QDockWidget(parent), + ui(new Ui::SearchResultsDock) +{ + ui->setupUi(this); + +#ifdef Q_OS_MACOS + // Set a slightly larger font on MacOS + QFont font("Courier New", 14); + ui->treeWidget->setFont(font); +#endif + + // Close the results when escape is pressed + new QShortcut(QKeySequence::Cancel, this, this, &SearchResultsDock::close, Qt::WidgetWithChildrenShortcut); + + connect(ui->treeWidget, &QTreeWidget::itemActivated, this, &SearchResultsDock::itemActivated); + connect(ui->treeWidget, &QTreeWidget::itemExpanded, this, &SearchResultsDock::itemExpanded); + connect(ui->btnCopyResults, &QPushButton::released,this, &SearchResultsDock::copySearchResultsToClipboard); + + connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, [=](const QPoint &pos) { + QTreeWidgetItem *item = ui->treeWidget->itemAt(pos); + + if (item == Q_NULLPTR) { + return; + } + + // Create the menu and show it + QMenu menu(this); + menu.addAction(tr("Collapse All"), this, &SearchResultsDock::collapseAll); + menu.addAction(tr("Expand All"), this, &SearchResultsDock::expandAll); + menu.addSeparator(); + menu.addAction(tr("Delete Entry"), this, [=]() { deleteEntry(item); }); + menu.addSeparator(); + menu.addAction(tr("Delete All"), this, &SearchResultsDock::deleteAll); + + menu.exec(QCursor::pos()); + }); +} + +SearchResultsDock::~SearchResultsDock() +{ + delete ui; +} + +void SearchResultsDock::newSearch(const QString searchTerm) +{ + show(); + + this->searchTerm = searchTerm; + + for (int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i) + { + const QTreeWidgetItem* topLevelItem = ui->treeWidget->topLevelItem(i); + ui->treeWidget->collapseItem(topLevelItem); + } + + currentSearch = new QTreeWidgetItem(ui->treeWidget); + currentSearch->setBackground(0, QColor(232, 232, 255)); + currentSearch->setForeground(0, QColor(0, 0, 170)); + currentSearch->setExpanded(true); + currentSearch->setFirstColumnSpanned(true); + + updateSearchStatus(); +} + +void SearchResultsDock::newFileEntry(ScintillaNext *editor) +{ + // Store a QPointer since there is no guarantee this editor will be around later + QPointer editor_pointer = editor; + + totalFileHitCount = 0; + currentFilePath = editor->isFile() ? editor->getFilePath() : editor->getName(); + + currentFile = new QTreeWidgetItem(currentSearch); + currentFile->setData(0, Qt::UserRole, QVariant::fromValue(editor_pointer)); + + currentFile->setBackground(0, QColor(213, 255, 213)); + currentFile->setForeground(0, QColor(0, 128, 0)); + currentFile->setExpanded(true); + currentFile->setFirstColumnSpanned(true); + + currentFileCount++; + updateSearchStatus(); +} + +void SearchResultsDock::newResultsEntry(const QString line, int lineNumber, int startPositionFromBeginning, int endPositionFromBeginning, int hitCount) +{ + QTreeWidgetItem *item = new QTreeWidgetItem(currentFile); + + // Scintilla internally references line numbers starting at 0, however it needs displayed starting at 1 + item->setText(0, QString::number(lineNumber + 1)); + item->setData(0, SearchResultData::LineNumber, lineNumber); + item->setData(0, SearchResultData::LinePosStart, startPositionFromBeginning); + item->setData(0, SearchResultData::LinePosEnd, endPositionFromBeginning); + item->setBackground(0, QBrush(QColor(220, 220, 220))); + item->setTextAlignment(0, Qt::AlignRight); + + item->setText(1, line); + + totalFileHitCount += hitCount; + totalHitCount += hitCount; + + updateSearchStatus(); +} + +void SearchResultsDock::completeSearch() +{ + currentSearch = Q_NULLPTR; + currentFile = Q_NULLPTR; + currentFileCount = 0; + totalFileHitCount = 0; + totalHitCount = 0; + + ui->treeWidget->resizeColumnToContents(0); + ui->treeWidget->resizeColumnToContents(1); +} + +void SearchResultsDock::collapseAll() const +{ + ui->treeWidget->collapseAll(); +} + +void SearchResultsDock::expandAll() const +{ + ui->treeWidget->expandAll(); +} + +void SearchResultsDock::deleteEntry(QTreeWidgetItem *item) +{ + QTreeWidgetItem *parent = item->parent(); + + if (parent != Q_NULLPTR) { + parent->removeChild(item); + delete item; + } + else { + const int index = ui->treeWidget->indexOfTopLevelItem(item); + delete ui->treeWidget->takeTopLevelItem(index); + } +} + +void SearchResultsDock::deleteAll() +{ + ui->treeWidget->clear(); +} + +void SearchResultsDock::itemActivated(QTreeWidgetItem *item, int column) +{ + Q_UNUSED(column); + + // Result entries have no children + // Make sure the entry has a parent since search entries can have no children + if (item->childCount() == 0 && item->parent() != Q_NULLPTR) { + QPointer editor = item->parent()->data(0, Qt::UserRole).value>(); + + // The editor may no longer exist + if (editor) { + int lineNumber = item->data(0, SearchResultData::LineNumber).toInt(); + int startPositionFromBeginning = item->data(0, SearchResultData::LinePosStart).toInt(); + int endPositionFromBeginning = item->data(0, SearchResultData::LinePosEnd).toInt(); + + emit searchResultActivated(editor, lineNumber, startPositionFromBeginning, endPositionFromBeginning); + } + } +} + +void SearchResultsDock::itemExpanded(QTreeWidgetItem *) +{ + ui->treeWidget->resizeColumnToContents(1); +} + +void SearchResultsDock::updateSearchStatus() +{ + currentSearch->setText(0, QStringLiteral("Search \"%1\" (%L2 hits in %L3 files)").arg(searchTerm).arg(totalHitCount).arg(currentFileCount)); + + if (currentFile) + currentFile->setText(0, QStringLiteral("%1 (%L2 hits)").arg(currentFilePath).arg(totalFileHitCount)); +} + +void SearchResultsDock::copySearchResultsToClipboard() +{ + QStringList results; + QTreeWidgetItemIterator it(ui->treeWidget); + + while (*it) { + const QTreeWidgetItem *item = *it; + results.append(QStringLiteral("%1 %2").arg(item->text(0)).arg(item->text(1))); + ++it; + } + + QGuiApplication::clipboard()->setText(results.join('\n')); +} + diff --git a/src/NotepadNext/docks/SearchResultsDock.h b/src/NotepadNext/docks/SearchResultsDock.h new file mode 100644 index 000000000..86d0efe09 --- /dev/null +++ b/src/NotepadNext/docks/SearchResultsDock.h @@ -0,0 +1,77 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see . + */ + + +#ifndef SEARCHRESULTSDOCK_H +#define SEARCHRESULTSDOCK_H + +#include + +#include "ISearchResultsHandler.h" + +namespace Ui { +class SearchResultsDock; +} + +class QTreeWidgetItem; +class ScintillaNext; + +class SearchResultsDock : public QDockWidget, public ISearchResultsHandler +{ + Q_OBJECT + +public: + explicit SearchResultsDock(QWidget *parent = nullptr); + ~SearchResultsDock(); + + void newSearch(const QString searchTerm) override; + void newFileEntry(ScintillaNext *editor) override; + void newResultsEntry(const QString line, int lineNumber, int startPositionFromBeginning, int endPositionFromBeginning, int hitCount=1) override; + void completeSearch() override; + +public slots: + void collapseAll() const; + void expandAll() const; + void deleteEntry(QTreeWidgetItem *item); + void deleteAll(); + +private slots: + void itemActivated(QTreeWidgetItem *item, int column); + void itemExpanded(QTreeWidgetItem *item); + void copySearchResultsToClipboard() ; + + +signals: + void searchResultActivated(ScintillaNext *editor, int lineNumber, int startPositionFromBeginning, int endPositionFromBeginning); + +private: + void updateSearchStatus(); + Ui::SearchResultsDock *ui; + + QString searchTerm; + QString currentFilePath; + + int currentFileCount = 0; + int totalFileHitCount = 0; + int totalHitCount = 0; + + QTreeWidgetItem *currentSearch = Q_NULLPTR; + QTreeWidgetItem *currentFile = Q_NULLPTR; +}; + +#endif // SEARCHRESULTSDOCK_H diff --git a/src/NotepadNext/docks/SearchResultsDock.ui b/src/NotepadNext/docks/SearchResultsDock.ui new file mode 100644 index 000000000..8e1471053 --- /dev/null +++ b/src/NotepadNext/docks/SearchResultsDock.ui @@ -0,0 +1,113 @@ + + + SearchResultsDock + + + + 0 + 0 + 400 + 300 + + + + Search Results + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Copy Results to Clipboard + + + + + + + :/icons/copy.png:/icons/copy.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Courier New + 10 + false + + + + Qt::CustomContextMenu + + + QFrame::NoFrame + + + QAbstractItemView::ScrollPerItem + + + 12 + + + true + + + 2 + + + false + + + + 1 + + + + + 2 + + + + + + + + + + + + diff --git a/src/NotepadNext/icons/NotepadNext.png b/src/NotepadNext/icons/NotepadNext.png new file mode 100644 index 000000000..25ce7a12a Binary files /dev/null and b/src/NotepadNext/icons/NotepadNext.png differ diff --git a/src/NotepadNext/icons/application_osx_terminal.png b/src/NotepadNext/icons/application_osx_terminal.png new file mode 100644 index 000000000..b3d8ce01e Binary files /dev/null and b/src/NotepadNext/icons/application_osx_terminal.png differ diff --git a/src/NotepadNext/icons/arrow_down.png b/src/NotepadNext/icons/arrow_down.png new file mode 100644 index 000000000..2c4e27937 Binary files /dev/null and b/src/NotepadNext/icons/arrow_down.png differ diff --git a/src/NotepadNext/icons/arrow_refresh.png b/src/NotepadNext/icons/arrow_refresh.png new file mode 100644 index 000000000..0de26566d Binary files /dev/null and b/src/NotepadNext/icons/arrow_refresh.png differ diff --git a/src/NotepadNext/icons/arrow_up.png b/src/NotepadNext/icons/arrow_up.png new file mode 100644 index 000000000..1ebb19324 Binary files /dev/null and b/src/NotepadNext/icons/arrow_up.png differ diff --git a/src/NotepadNext/icons/bin.png b/src/NotepadNext/icons/bin.png new file mode 100644 index 000000000..ebad933c8 Binary files /dev/null and b/src/NotepadNext/icons/bin.png differ diff --git a/src/NotepadNext/icons/bin_closed.png b/src/NotepadNext/icons/bin_closed.png new file mode 100644 index 000000000..afe22ba99 Binary files /dev/null and b/src/NotepadNext/icons/bin_closed.png differ diff --git a/src/NotepadNext/icons/closeAll.png b/src/NotepadNext/icons/closeAll.png new file mode 100644 index 000000000..e7559f753 Binary files /dev/null and b/src/NotepadNext/icons/closeAll.png differ diff --git a/src/NotepadNext/icons/closeFile.png b/src/NotepadNext/icons/closeFile.png new file mode 100644 index 000000000..294a0d1b1 Binary files /dev/null and b/src/NotepadNext/icons/closeFile.png differ diff --git a/src/NotepadNext/icons/cog.png b/src/NotepadNext/icons/cog.png new file mode 100644 index 000000000..67de2c6cc Binary files /dev/null and b/src/NotepadNext/icons/cog.png differ diff --git a/src/NotepadNext/icons/copy.png b/src/NotepadNext/icons/copy.png new file mode 100644 index 000000000..d6f474903 Binary files /dev/null and b/src/NotepadNext/icons/copy.png differ diff --git a/src/NotepadNext/icons/cut.png b/src/NotepadNext/icons/cut.png new file mode 100644 index 000000000..bfc593f36 Binary files /dev/null and b/src/NotepadNext/icons/cut.png differ diff --git a/src/NotepadNext/icons/find.png b/src/NotepadNext/icons/find.png new file mode 100644 index 000000000..f1eb91492 Binary files /dev/null and b/src/NotepadNext/icons/find.png differ diff --git a/src/NotepadNext/icons/findReplace.png b/src/NotepadNext/icons/findReplace.png new file mode 100644 index 000000000..dd8e854a6 Binary files /dev/null and b/src/NotepadNext/icons/findReplace.png differ diff --git a/src/NotepadNext/icons/folder_go.png b/src/NotepadNext/icons/folder_go.png new file mode 100644 index 000000000..34a736f70 Binary files /dev/null and b/src/NotepadNext/icons/folder_go.png differ diff --git a/src/NotepadNext/icons/indentGuide.png b/src/NotepadNext/icons/indentGuide.png new file mode 100644 index 000000000..411e52e12 Binary files /dev/null and b/src/NotepadNext/icons/indentGuide.png differ diff --git a/src/NotepadNext/icons/invisibleChar.png b/src/NotepadNext/icons/invisibleChar.png new file mode 100644 index 000000000..fff72afaa Binary files /dev/null and b/src/NotepadNext/icons/invisibleChar.png differ diff --git a/src/NotepadNext/icons/newfile.png b/src/NotepadNext/icons/newfile.png new file mode 100644 index 000000000..788c3fbef Binary files /dev/null and b/src/NotepadNext/icons/newfile.png differ diff --git a/src/NotepadNext/icons/openFile.png b/src/NotepadNext/icons/openFile.png new file mode 100644 index 000000000..f940e55d1 Binary files /dev/null and b/src/NotepadNext/icons/openFile.png differ diff --git a/src/NotepadNext/icons/paste.png b/src/NotepadNext/icons/paste.png new file mode 100644 index 000000000..af896f913 Binary files /dev/null and b/src/NotepadNext/icons/paste.png differ diff --git a/src/NotepadNext/icons/playRecord.png b/src/NotepadNext/icons/playRecord.png new file mode 100644 index 000000000..bc1414802 Binary files /dev/null and b/src/NotepadNext/icons/playRecord.png differ diff --git a/src/NotepadNext/icons/playRecord_m.png b/src/NotepadNext/icons/playRecord_m.png new file mode 100644 index 000000000..66c582de4 Binary files /dev/null and b/src/NotepadNext/icons/playRecord_m.png differ diff --git a/src/NotepadNext/icons/printer.png b/src/NotepadNext/icons/printer.png new file mode 100644 index 000000000..a350d1871 Binary files /dev/null and b/src/NotepadNext/icons/printer.png differ diff --git a/src/NotepadNext/icons/readonly.png b/src/NotepadNext/icons/readonly.png new file mode 100644 index 000000000..c92403085 Binary files /dev/null and b/src/NotepadNext/icons/readonly.png differ diff --git a/src/NotepadNext/icons/redo.png b/src/NotepadNext/icons/redo.png new file mode 100644 index 000000000..edd280b23 Binary files /dev/null and b/src/NotepadNext/icons/redo.png differ diff --git a/src/NotepadNext/icons/saveAll.png b/src/NotepadNext/icons/saveAll.png new file mode 100644 index 000000000..643aa1821 Binary files /dev/null and b/src/NotepadNext/icons/saveAll.png differ diff --git a/src/NotepadNext/icons/saveRecord.png b/src/NotepadNext/icons/saveRecord.png new file mode 100644 index 000000000..ae2ed95c9 Binary files /dev/null and b/src/NotepadNext/icons/saveRecord.png differ diff --git a/src/NotepadNext/icons/saved.png b/src/NotepadNext/icons/saved.png new file mode 100644 index 000000000..31f162089 Binary files /dev/null and b/src/NotepadNext/icons/saved.png differ diff --git a/src/NotepadNext/icons/startRecord.png b/src/NotepadNext/icons/startRecord.png new file mode 100644 index 000000000..e187e24e0 Binary files /dev/null and b/src/NotepadNext/icons/startRecord.png differ diff --git a/src/NotepadNext/icons/stopRecord.png b/src/NotepadNext/icons/stopRecord.png new file mode 100644 index 000000000..95a2f571e Binary files /dev/null and b/src/NotepadNext/icons/stopRecord.png differ diff --git a/src/NotepadNext/icons/table_delete.png b/src/NotepadNext/icons/table_delete.png new file mode 100644 index 000000000..b85916d92 Binary files /dev/null and b/src/NotepadNext/icons/table_delete.png differ diff --git a/src/NotepadNext/icons/table_edit.png b/src/NotepadNext/icons/table_edit.png new file mode 100644 index 000000000..bfcb0249a Binary files /dev/null and b/src/NotepadNext/icons/table_edit.png differ diff --git a/src/NotepadNext/icons/table_row_delete.png b/src/NotepadNext/icons/table_row_delete.png new file mode 100644 index 000000000..54c69691e Binary files /dev/null and b/src/NotepadNext/icons/table_row_delete.png differ diff --git a/src/NotepadNext/icons/table_row_insert.png b/src/NotepadNext/icons/table_row_insert.png new file mode 100644 index 000000000..ff5925efd Binary files /dev/null and b/src/NotepadNext/icons/table_row_insert.png differ diff --git a/src/NotepadNext/icons/text_indent.png b/src/NotepadNext/icons/text_indent.png new file mode 100644 index 000000000..936453234 Binary files /dev/null and b/src/NotepadNext/icons/text_indent.png differ diff --git a/src/NotepadNext/icons/text_indent_remove.png b/src/NotepadNext/icons/text_indent_remove.png new file mode 100644 index 000000000..1651b074e Binary files /dev/null and b/src/NotepadNext/icons/text_indent_remove.png differ diff --git a/src/NotepadNext/icons/undo.png b/src/NotepadNext/icons/undo.png new file mode 100644 index 000000000..be058d23e Binary files /dev/null and b/src/NotepadNext/icons/undo.png differ diff --git a/src/NotepadNext/icons/unsaved.png b/src/NotepadNext/icons/unsaved.png new file mode 100644 index 000000000..7779313d6 Binary files /dev/null and b/src/NotepadNext/icons/unsaved.png differ diff --git a/src/NotepadNext/icons/wrap.png b/src/NotepadNext/icons/wrap.png new file mode 100644 index 000000000..6fdd8d235 Binary files /dev/null and b/src/NotepadNext/icons/wrap.png differ diff --git a/src/NotepadNext/icons/wrapindicator.png b/src/NotepadNext/icons/wrapindicator.png new file mode 100644 index 000000000..dcca1cee6 Binary files /dev/null and b/src/NotepadNext/icons/wrapindicator.png differ diff --git a/src/NotepadNext/icons/zoomIn.png b/src/NotepadNext/icons/zoomIn.png new file mode 100644 index 000000000..0495b58f0 Binary files /dev/null and b/src/NotepadNext/icons/zoomIn.png differ diff --git a/src/NotepadNext/icons/zoomOut.png b/src/NotepadNext/icons/zoomOut.png new file mode 100644 index 000000000..87d8baccd Binary files /dev/null and b/src/NotepadNext/icons/zoomOut.png differ diff --git a/src/NotepadNext/languages/actionscript.lua b/src/NotepadNext/languages/actionscript.lua new file mode 100644 index 000000000..3362b3b19 --- /dev/null +++ b/src/NotepadNext/languages/actionscript.lua @@ -0,0 +1,124 @@ +local L = {} + +L.lexer = "cpp" + +L.singleLineComment = "// " + +L.extensions = { + "as", + "mx", +} + +L.keywords = { + [0] = "add for lt tellTarget and function ne this break ge new typeof continue gt not var delete if on void do ifFrameLoaded onClipEvent while else in or with eq le return instanceof case default switch", + [2] = "arguments constructor class dynamic false extends implements import interface intrinsic newline null private public super static true undefined Accessibility Arguments Array Boolean Button Camera ContextMenu ContextMenuItem CustomActions Color Date Error Function Key LoadVars LocalConnection Math Microphone Mouse MovieClip MovieClipLoader NetConnection NetStream Number PrintJob Object TextField StyleSheet TextFormat TextSnapshot SharedObject Selection Sound Stage String System XML XMLNode XMLSocket Void abs acos asin atan atan2 ceil cos exp floor log max min pow random round sin sqrt tan onActivity onChanged onClose onConnect onData onDragOut onDragOver onEnterFrame onID3 onKeyDown onKeyUp onKillFocus onLoad onLoadComplete onLoadError onLoadInit onLoadProgress onLoadStart onMouseDown onMouseMove onMouseUp onMouseWheel onPress onRelease onReleaseOutside onResize onRollOut onRollOver onScroller onSelect onSetFocus onSoundComplete onStatus onUnload onUpdate onXML addListener addPage addProperty addRequestHeader allowDomain allowInsecureDomain appendChild apply applyChanges asfunction attachAudio attachMovie attachSound attachVideo beginFill beginGradientFill call charAt charCodeAt clear clearInterval cloneNode close concat connect copy createElement createEmptyMovieClip createTextField createTextNode curveTo domain duplicateMovieClip endFill escape eval evaluate findText fscommand flush fromCharCode get getAscii getBeginIndex getBounds getBytesLoaded getBytesTotal getCaretIndex getCode getCount getDate getDay getDepth getEndIndex getFocus getFontList getFullYear getHours getInstanceAtDepth getLocal getMilliseconds getMinutes getMonth getNewTextFormat getNextHighestDepth getPan getProggress getProperty getRGB getSeconds getSelected getSelectedText getSize getStyle getStyleNames getSWFVersion getText getTextExtent getTextFormat getTextSnapshot getTime getTimer getTimezoneOffset getTransform getURL getUTCDate getUTCDay getUTCFullYear getUTCHours getUTCMilliseconds getUTCMinutes getUTCMonth getUTCSeconds getVersion getVolume getYear globalToLocal gotoAndPlay gotoAndStop hasChildNodes hide hideBuiltInItems hitTest hitTestTextNearPos indexOf insertBefore install isActive isDown isToggled join lastIndexOf lineStyle lineTo list load loadClip loadMovie loadMovieNum loadSound loadVariables loadVariablesNum localToGlobal mbchr mblength mbord mbsubstring MMExecute moveTo nextFrame nextScene parseCSS parseFloat parseInt parseXML pause play pop prevScene print printAsBitmap printAsBitmapNum printNum push registerClass removeListener removeMovieClip removeNode removeTextField replaceSel replaceText reverse seek send sendAndLoad setBufferTime set setDate setFocus setFullYear setGain setHours setInterval setMask setMilliseconds setMinutes setMode setMonth setMotionLevel setNewTextFormat setPan setProperty setQuality setRate setRGB setSeconds setSelectColor setSelected setSelection setSilenceLevel setStyle setTextFormat setTime setTransform setUseEchoSuppression setUTCDate setUTCFullYear setUTCHours setUTCMilliseconds setUTCMinutes setUTCMonth setUTCSeconds setVolume setYear shift show showSettings silenceLevel silenceTimeout slice sort sortOn splice split start startDrag stop stopAllSounds stopDrag substr substring swapDepths toggleHighQuality toLowerCase toString toUpperCase trace unescape uninstall unLoadClip unloadMovie unloadMovieNum unshift unwatch updateAfterEvent updateProperties useEchoSuppression valueOf watch endinitclip include initclip __proto__ _accProps _alpha _currentframe _droptarget _focusrect _framesloaded _global _height _highquality _level _lockroot _name _parent _quality _root _rotation _soundbuftime _target _totalframes _url _visible _width _x _xmouse _xscale _y _ymouse _yscale activityLevel align attributes autoSize avHardwareDisable background backgroundColor bandwidth blockIndent bold border borderColor bottomScroll bufferLenght bufferTime builtInItems bullet bytesLoaded bytesTotal callee caller capabilities caption childNodes color condenseWhite contentType currentFps customItems data deblocking docTypeDecl duration embedFonts enabled exactSettings firstChild focusEnabled font fps gain globalStyleFormat hasAccessibility hasAudio hasAudioEncoder hasEmbeddedVideo hasMP3 hasPrinting hasScreenBroadcast hasScreenPlayback hasStreamingAudio hasStreamingVideo hasVideoEncoder height hitArea hscroll html htmlText indent index italic instanceof int ignoreWhite isDebugger isFinite language lastChild leading leftMargin length loaded localFileReadDisable manufacturer maxChars maxhscroll maxscroll menu message motionLevel motionTimeout mouseWheelEnabled multiline muted name names NaN nextSibling nodeName nodeType nodeValue os parentNode password pixelAspectRatio playerType previousSibling prototype quality rate restrict resolutionX resolutionY rightMargin scaleMode screenColor screenDPI screenResolutionX screenResolutionY scroll selectable separatorBefore showMenu size smoothing status styleSheet tabChildren tabEnabled tabIndex tabStops target targetPath text textColor textHeight textWidth time trackAsMenu type underline url useCodepage useHandCursor variable version visible width wordWrap xmlDecl", +} + +L.styles = { + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["FUNCTION"] = { + id = 20, + fgColor = rgb(0x95004A), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT"] = { + id = 23, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT DOC"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/ada.lua b/src/NotepadNext/languages/ada.lua new file mode 100644 index 000000000..89ab0204c --- /dev/null +++ b/src/NotepadNext/languages/ada.lua @@ -0,0 +1,72 @@ +local L = {} + +L.lexer = "ada" + +L.singleLineComment = "-- " + +L.extensions = { + "ada", + "ads", + "adb", +} + +L.keywords = { + [0] = "abort abs abstract accept access aliased all and array at begin body case constant declare delay delta digits do else elsif end entry exception exit for function generic goto if in interface is limited loop mod new not null of or others out overriding package pragma private procedure protected raise range record rem renames requeue return reverse select separate some subtype synchronized tagged task terminate then type until use when while with xor", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 1, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 2, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["DELIMITER"] = { + id = 4, + fgColor = rgb(0xFF8080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["CHARACTER"] = { + id = 5, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT LINE"] = { + id = 10, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["ILLEGAL"] = { + id = 11, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/asm.lua b/src/NotepadNext/languages/asm.lua new file mode 100644 index 000000000..846a832f7 --- /dev/null +++ b/src/NotepadNext/languages/asm.lua @@ -0,0 +1,98 @@ +local L = {} + +L.lexer = "asm" + +L.singleLineComment = "; " + +L.extensions = { + "asm", +} + +L.keywords = { + [0] = "aaa aad aam aas adc add and call cbw cdqe clc cld cli cmc cmp cmps cmpsb cmpsw cwd daa das dec div esc hlt idiv imul in inc int into iret ja jae jb jbe jc jcxz je jg jge jl jle jmp jna jnae jnb jnbe jnc jne jng jnge jnl jnle jno jnp jns jnz jo jp jpe jpo js jz lahf lds lea les lods lodsb lodsw loop loope loopew loopne loopnew loopnz loopnzw loopw loopz loopzw mov movabs movs movsb movsw mul neg nop not or out pop popf push pushf rcl rcr ret retf retn rol ror sahf sal sar sbb scas scasb scasw shl shr stc std sti stos stosb stosw sub test wait xchg xlat xlatb xor bound enter ins insb insw leave outs outsb outsw popa pusha pushw arpl lar lsl sgdt sidt sldt smsw str verr verw clts lgdt lidt lldt lmsw ltr bsf bsr bt btc btr bts cdq cmpsd cwde insd iretd iretdf iretf jecxz lfs lgs lodsd loopd looped loopned loopnzd loopzd lss movsd movsx movsxd movzx outsd popad popfd pushad pushd pushfd scasd seta setae setb setbe setc sete setg setge setl setle setna setnae setnb setnbe setnc setne setng setnge setnl setnle setno setnp setns setnz seto setp setpe setpo sets setz shld shrd stosd bswap cmpxchg invd invlpg wbinvd xadd lock rep repe repne repnz repz cflush cpuid emms femms cmovo cmovno cmovb cmovc cmovnae cmovae cmovnb cmovnc cmove cmovz cmovne cmovnz cmovbe cmovna cmova cmovnbe cmovs cmovns cmovp cmovpe cmovnp cmovpo cmovl cmovnge cmovge cmovnl cmovle cmovng cmovg cmovnle cmpxchg486 cmpxchg8b loadall loadall286 ibts icebp int1 int3 int01 int03 iretw popaw popfw pushaw pushfw rdmsr rdpmc rdshr rdtsc rsdc rsldt rsm rsts salc smi smint smintold svdc svldt svts syscall sysenter sysexit sysret ud0 ud1 ud2 umov xbts wrmsr wrshr", + [1] = "f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcom fcomp fcompp fdecstp fdisi fdiv fdivp fdivr fdivrp feni ffree fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisub fisubr fld fld1 fldcw fldenv fldenvw fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnsavew fnstcw fnstenv fnstenvw fnstsw fpatan fprem fptan frndint frstor frstorw fsave fsavew fscale fsqrt fst fstcw fstenv fstenvw fstp fstsw fsub fsubp fsubr fsubrp ftst fwait fxam fxch fxtract fyl2x fyl2xp1 fsetpm fcos fldenvd fnsaved fnstenvd fprem1 frstord fsaved fsin fsincos fstenvd fucom fucomp fucompp fcomi fcomip ffreep fcmovb fcmove fcmovbe fcmovu fcmovnb fcmovne fcmovnbe fcmovnu", + [2] = "ah al ax bh bl bp bx ch cl cr0 cr2 cr3 cr4 cs cx dh di dl dr0 dr1 dr2 dr3 dr6 dr7 ds dx eax ebp ebx ecx edi edx es esi esp fs gs rax rbx rcx rdx rdi rsi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 r8d r9d r10d r11d r12d r13d r14d r15d r8w r9w r10w r11w r12w r13w r14w r15w r8b r9b r10b r11b r12b r13b r14b r15b si sp ss st tr3 tr4 tr5 tr6 tr7 st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15", + [3] = ".186 .286 .286c .286p .287 .386 .386c .386p .387 .486 .486p .8086 .8087 .alpha .break .code .const .continue .cref .data .data? .dosseg .else .elseif .endif .endw .err .err1 .err2 .errb .errdef .errdif .errdifi .erre .erridn .erridni .errnb .errndef .errnz .exit .fardata .fardata? .if .lall .lfcond .list .listall .listif .listmacro .listmacroall .model .no87 .nocref .nolist .nolistif .nolistmacro .radix .repeat .sall .seq .sfcond .stack .startup .tfcond .type .until .untilcxz .while .xall .xcref .xlist alias align assume catstr comm comment db dd df dosseg dq dt dup dw echo else elseif elseif1 elseif2 elseifb elseifdef elseifdif elseifdifi elseife elseifidn elseifidni elseifnb elseifndef end endif endm endp ends eq equ even exitm extern externdef extrn for forc ge goto group gt high highword if if1 if2 ifb ifdef ifdif ifdifi ife ifidn ifidni ifnb ifndef include includelib instr invoke irp irpc label le length lengthof local low lowword lroffset lt macro mask mod .msfloat name ne offset opattr option org %out page popcontext proc proto ptr public purge pushcontext record repeat rept seg segment short size sizeof sizestr struc struct substr subtitle subttl textequ this title type typedef union while width resb resw resd resq rest incbin times %define %idefine %xdefine %xidefine %undef %assign %iassign %strlen %substr %macro %imacro %endmacro %rotate %if %elif %else %endif %ifdef %ifndef %elifdef %elifndef %ifmacro %ifnmacro %elifmacro %elifnmacro %ifctk %ifnctk %elifctk %elifnctk %ifidn %ifnidn %elifidn %elifnidn %ifidni %ifnidni %elifidni %elifnidni %ifid %ifnid %elifid %elifnid %ifstr %ifnstr %elifstr %elifnstr %ifnum %ifnnum %elifnum %elifnnum %error %rep %endrep %exitrep %include %push %pop %repl endstruc istruc at iend alignb %arg %stacksize %local %line bits use16 use32 section absolute global common cpu import export", + [4] = "$ ? @b @f addr basic byte c carry? dword far far16 fortran fword near near16 overflow? parity? pascal qword real4 real8 real10 sbyte sdword sign? stdcall sword syscall tbyte vararg word zero? flat near32 far32 abs all assumes at casemap common compact cpu dotname emulator epilogue error export expr16 expr32 farstack forceframe huge language large listing ljmp loadds m510 medium memory nearstack nodotname noemulator nokeyword noljmp nom510 none nonunique nooldmacros nooldstructs noreadonly noscoped nosignextend nothing notpublic oldmacros oldstructs os_dos para private prologue radix readonly req scoped setif2 smallstack tiny use16 use32 uses a16 a32 o16 o32 nosplit $$ seq wrt small .text .data .bss %0 %1 %2 %3 %4 %5 %6 %7 %8 %9", + [5] = "addpd addps addsd addss andpd andps andnpd andnps cmpeqpd cmpltpd cmplepd cmpunordpd cmpnepd cmpnltpd cmpnlepd cmpordpd cmpeqps cmpltps cmpleps cmpunordps cmpneps cmpnltps cmpnleps cmpordps cmpeqsd cmpltsd cmplesd cmpunordsd cmpnesd cmpnltsd cmpnlesd cmpordsd cmpeqss cmpltss cmpless cmpunordss cmpness cmpnltss cmpnless cmpordss comisd comiss cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd cvtps2pi cvtss2sd cvtss2si cvtsd2si cvtsd2ss cvtsi2sd cvtsi2ss cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi cvttsd2si cvttss2si divpd divps divsd divss fxrstor fxsave ldmxscr lfence mfence maskmovdqu maskmovdq maxpd maxps paxsd maxss minpd minps minsd minss movapd movaps movdq2q movdqa movdqu movhlps movhpd movhps movd movq movlhps movlpd movlps movmskpd movmskps movntdq movnti movntpd movntps movntq movq2dq movsd movss movupd movups mulpd mulps mulsd mulss orpd orps packssdw packsswb packuswb paddb paddsb paddw paddsw paddd paddsiw paddq paddusb paddusw pand pandn pause paveb pavgb pavgw pavgusb pdistib pextrw pcmpeqb pcmpeqw pcmpeqd pcmpgtb pcmpgtw pcmpgtd pf2id pf2iw pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pmachriw pmaddwd pmagw pmaxsw pmaxub pminsw pminub pmovmskb pmulhrwc pmulhriw pmulhrwa pmulhuw pmulhw pmullw pmuludq pmvzb pmvnzb pmvlzb pmvgezb pfnacc pfpnacc por prefetch prefetchw prefetchnta prefetcht0 prefetcht1 prefetcht2 pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pinsrw psadbw pshufd pshufhw pshuflw pshufw psllw pslld psllq pslldq psraw psrad psrlw psrld psrlq psrldq psubb psubw psubd psubq psubsb psubsw psubusb psubusw psubsiw pswapd punpckhbw punpckhwd punpckhdq punpckhqdq punpcklbw punpcklwd punpckldq punpcklqdq pxor rcpps rcpss rsqrtps rsqrtss sfence shufpd shufps sqrtpd sqrtps sqrtsd sqrtss stmxcsr subpd subps subsd subss ucomisd ucomiss unpckhpd unpckhps unpcklpd unpcklps xorpd xorps", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 4, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CPU INSTRUCTION"] = { + id = 6, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MATH INSTRUCTION"] = { + id = 7, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["REGISTER"] = { + id = 8, + fgColor = rgb(0x8080FF), + bgColor = rgb(0xFFFFCC), + fontStyle = 1, + }, + ["DIRECTIVE"] = { + id = 9, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["DIRECTIVE OPERAND"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT BLOCK"] = { + id = 11, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 12, + fgColor = rgb(0x808000), + bgColor = rgb(defaultBg), + }, + ["EXT INSTRUCTION"] = { + id = 14, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/asn1.lua b/src/NotepadNext/languages/asn1.lua new file mode 100644 index 000000000..fdd2e557b --- /dev/null +++ b/src/NotepadNext/languages/asn1.lua @@ -0,0 +1,75 @@ +local L = {} + +L.lexer = "asn1" + +L.extensions = { + "mib", +} + +L.keywords = { + [0] = "ACCESS AGENT AUGMENTS BEGIN BITS CAPABILITIES CHOICE COMPLIANCE CONTACT CONVENTION DEFINITIONS DEFVAL DESCRIPTION DISPLAY END ENTERPRISE EXPORTS FALSE FROM GROUP GROUPS HINT IDENTITY IMPLIED IMPORTS INCLUDES INDEX INFO LAST MANDATORY MAX MIN MODULE NOTATION NOTIFICATION NULL OBJECTS OBJECT-TYPE OF ORGANIZATION PRODUCT RELEASE REFERENCE REQUIRES REVISION SEQUENCE SIZE STATUS SUPPORTS SYNTAX TEXTUAL TRAP TYPE TRAP-TYPE UPDATED VALUE VARIABLES VARIATION WRITE", + [1] = "accessible create current deprecated for mandatory not notify not-accessible obsolete only optional read read-only read-write write", + [2] = "ABSENT ANY APPLICATION BIT BOOLEAN BY COMPONENT COMPONENTS DEFAULT DEFINED ENUMERATED EXPLICIT EXTERNAL IMPLICIT INIFINITY MAX MIN MINUS OPTIONAL PRESENT PRIVATE REAL SET TAGS TRUE", + [3] = "Counter Counter32 Counter64 DisplayString Gauge Gauge32 IDENTIFIER INTEGER Integer32 IpAddress NetworkAddress NsapAddress OBJECT OCTET Opaque PhysAddress STRING TimeTicks UInteger32 UNITS Unsigned32", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIERS"] = { + id = 2, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DOUBLE QUOTED STRING"] = { + id = 3, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["NUMERIC OID DEFINITION"] = { + id = 4, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NON OID NUMBERS"] = { + id = 5, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["KEYWORDS"] = { + id = 6, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["ATTRIBUTES"] = { + id = 7, + fgColor = rgb(0xF07800), + bgColor = rgb(defaultBg), + }, + ["DESCRIPTORS"] = { + id = 8, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["TYPES"] = { + id = 9, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["OPERATORS"] = { + id = 10, + fgColor = rgb(0x222222), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/asp.lua b/src/NotepadNext/languages/asp.lua new file mode 100644 index 000000000..dfb09b112 --- /dev/null +++ b/src/NotepadNext/languages/asp.lua @@ -0,0 +1,59 @@ +local L = {} + +L.lexer = "asp" + +L.singleLineComment = "' " + +L.extensions = { + "asp", +} + +L.keywords = { + [0] = "addhandler addressof andalso alias and ansi as assembly attribute auto begin boolean byref byte byval call case catch cbool cbyte cchar cdate cdec cdbl char cint class clng cobj compare const continue cshort csng cstr ctype currency date decimal declare default delegate dim do double each else elseif end enum erase error event exit explicit false finally for friend function get gettype global gosub goto handles if implement implements imports in inherits integer interface is let lib like load long loop lset me mid mod module mustinherit mustoverride mybase myclass namespace new next not nothing notinheritable notoverridable object on option optional or orelse overloads overridable overrides paramarray preserve private property protected public raiseevent readonly redim rem removehandler rset resume return select set shadows shared short single static step stop string structure sub synclock then throw to true try type typeof unload unicode until variant wend when while with withevents writeonly xor", +} + +L.styles = { + ["DEFAULT"] = { + id = 81, + fgColor = rgb(TypeColor), + bgColor = rgb(0xC4F9FD), + }, + ["COMMENTLINE"] = { + id = 82, + fgColor = rgb(0x008000), + bgColor = rgb(0xC4F9FD), + }, + ["NUMBER"] = { + id = 83, + fgColor = rgb(0xFF0000), + bgColor = rgb(0xC4F9FD), + }, + ["WORD"] = { + id = 84, + fgColor = rgb(OperatorColor), + bgColor = rgb(0xC4F9FD), + fontStyle = 1, + }, + ["STRING"] = { + id = 85, + fgColor = rgb(0x808080), + bgColor = rgb(0xC4F9FD), + }, + ["IDENTIFIER"] = { + id = 86, + fgColor = rgb(defaultFg), + bgColor = rgb(0xC4F9FD), + }, + ["ASPSYMBOL"] = { + id = 15, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFFFF00), + fontStyle = 1, + }, + ["SCRIPTTYPE"] = { + id = 16, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFFC000), + }, +} +return L diff --git a/src/NotepadNext/languages/autoit.lua b/src/NotepadNext/languages/autoit.lua new file mode 100644 index 000000000..f19db8c48 --- /dev/null +++ b/src/NotepadNext/languages/autoit.lua @@ -0,0 +1,101 @@ +local L = {} + +L.lexer = "autoit" + +L.singleLineComment = "; " + +L.extensions = { + "au3", +} + +L.keywords = { + [0] = "and byref case const continuecase continueloop default dim do else elseif endfunc endif endselect endswitch enum exit exitloop false for func global if in local next not null or redim return select static step switch then to true until wend while", + [1] = "abs acos adlibdisable adlibenable asc asin atan autoitsetoption autoitwingettitle autoitwinsettitle bitand bitnot bitor bitshift bitxor blockinput break call cdtray chr clipget clipput controlclick controlcommand controldisable controlenable controlfocus controlgetfocus controlgetpos controlgettext controlhide controlmove controlsend controlsettext controlshow cos dec dircopy dircreate dirmove dirremove drivegetdrive drivegetfilesystem drivegetlabel drivegetserial drivegettype drivesetlabel drivespacefree drivespacetotal drivestatus envget envset envupdate eval exp filechangedir fileclose filecopy filecreateshortcut filedelete fileexists filefindfirstfile filefindnextfile filegetattrib filegetlongname filegetshortname filegetsize filegettime filegetversion fileinstall filemove fileopen fileopendialog fileread filereadline filerecycle filerecycleempty filesavedialog fileselectfolder filesetattrib filesettime filewrite filewriteline guicreate guicreateex guidefaultfont guidelete guigetcontrolstate guihide guimsg guiread guirecvmsg guisendmsg guisetcontrol guisetcontroldata guisetcontrolex guisetcontrolfont guisetcontrolnotify guisetcoord guisetcursor guishow guiwaitclose guiwrite hex hotkeyset inidelete iniread iniwrite inputbox int isadmin isarray isdeclared isfloat isint isnumber isstring log memgetstats mod mouseclick mouseclickdrag mousedown mousegetcursor mousegetpos mousemove mouseup mousewheel msgbox number pixelchecksum pixelgetcolor pixelsearch processclose processexists processsetpriority processwait processwaitclose progressoff progresson progressset random regdelete regenumkey regenumval regread regwrite round run runasset runwait send seterror shutdown sin sleep soundplay soundsetwavevolume splashimageon splashoff splashtexton sqrt statusbargettext string stringaddcr stringformat stringinstr stringisalnum stringisalpha stringisascii stringisdigit stringisfloat stringisint stringislower stringisspace stringisupper stringisxdigit stringleft stringlen stringlower stringmid stringreplace stringright stringsplit stringstripcr stringstripws stringtrimleft stringtrimright stringupper tan timerstart timerstop tooltip traytip ubound urldownloadtofile winactivate winactive winclose winexists wingetcaretpos wingetclasslist wingetclientsize wingethandle wingetpos wingetstate wingettext wingettitle winkill winmenuselectitem winminimizeall winminimizeallundo winmove winsetontop winsetstate winsettitle winwait winwaitactive winwaitclose winwaitnotactive", + [2] = "@appdatacommondir @appdatadir @autoitexe @autoitpid @autoitversion @autoitx64 @com_eventobj @commonfilesdir @compiled @computername @comspec @cpuarch @cr @crlf @desktopcommondir @desktopdepth @desktopdir @desktopheight @desktoprefresh @desktopwidth @documentscommondir @error @exitcode @exitmethod @extended @favoritescommondir @favoritesdir @gui_ctrlhandle @gui_ctrlid @gui_dragfile @gui_dragid @gui_dropid @gui_winhandle @homedrive @homepath @homeshare @hotkeypressed @hour @ipaddress1 @ipaddress2 @ipaddress3 @ipaddress4 @kblayout @lf @localappdatadir @logondnsdomain @logondomain @logonserver @mday @min @mon @msec @muilang @mydocumentsdir @numparams @osarch @osbuild @oslang @osservicepack @ostype @osversion @programfilesdir @programscommondir @programsdir @scriptdir @scriptfullpath @scriptlinenumber @scriptname @sec @startmenucommondir @startmenudir @startupcommondir @startupdir @sw_disable @sw_enable @sw_hide @sw_lock @sw_maximize @sw_minimize @sw_restore @sw_show @sw_showdefault @sw_showmaximized @sw_showminimized @sw_showminnoactive @sw_showna @sw_shownoactivate @sw_shownormal @sw_unlock @systemdir @tab @tempdir @tray_id @trayiconflashing @trayiconvisible @username @userprofiledir @wday @windowsdir @workingdir @yday @year", + [3] = "{!} {#} {^} {{} {}} {+} {alt} {altdown} {altup} {appskey} {asc} {backspace} {browser_back} {browser_favorites} {browser_forward} {browser_home} {browser_refresh} {browser_search} {browser_stop} {bs} {capslock} {ctrlbreak} {ctrldown} {ctrlup} {del} {delete} {down} {end} {enter} {esc} {escape} {f1} {f10} {f11} {f12} {f2} {f3} {f4} {f5} {f6} {f7} {f8} {f9} {home} {ins} {insert} {lalt} {launch_app1} {launch_app2} {launch_mail} {launch_media} {lctrl} {left} {lshift} {lwin} {lwindown} {media_next} {media_play_pause} {media_prev} {media_stop} {numlock} {numpad0} {numpad1} {numpad2} {numpad3} {numpad4} {numpad5} {numpad6} {numpad7} {numpad8} {numpad9} {numpadadd} {numpaddiv} {numpaddot} {numpadenter} {numpadmult} {numpadsub} {pause} {pgdn} {pgup} {printscreen} {ralt} {rctrl} {right} {rshift} {rwin} {rwindown} {scrolllock} {shiftdown} {shiftup} {sleep} {space} {tab} {up} {volume_down} {volume_mute} {volume_up}", + [4] = "#include #include-once #pragma", + [5] = "#region #endregion", + [6] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["FUNCTION"] = { + id = 4, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MACRO"] = { + id = 6, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 8, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VARIABLE"] = { + id = 9, + fgColor = rgb(0xFF0080), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["SENT"] = { + id = 10, + fgColor = rgb(0x8080C0), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 11, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["SPECIAL"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["EXPAND"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMOBJ"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/avs.lua b/src/NotepadNext/languages/avs.lua new file mode 100644 index 000000000..0c3a2ed21 --- /dev/null +++ b/src/NotepadNext/languages/avs.lua @@ -0,0 +1,106 @@ +local L = {} + +L.lexer = "avs" + +L.singleLineComment = "# " + +L.extensions = { + "avs", + "avsi", +} + +L.keywords = { + [0] = "true false return global", + [1] = "addborders alignedsplice amplify amplifydb animate applyrange assumebff assumefieldbased assumefps assumeframebased assumesamplerate assumescaledfps assumetff audiodub audiodubex avifilesource avisource bicubicresize bilinearresize blackmanresize blackness blankclip blur bob cache changefps colorbars colorkeymask coloryuv compare complementparity conditionalfilter conditionalreader convertaudio convertaudioto16bit convertaudioto24bit convertaudioto32bit convertaudioto8bit convertaudiotofloat convertbacktoyuy2 convertfps converttobackyuy2 converttomono converttorgb converttorgb24 converttorgb32 converttoy8 converttoyv16 converttoyv24 converttoyv411 converttoyuy2 converttoyv12 crop cropbottom delayaudio deleteframe dissolve distributor doubleweave duplicateframe ensurevbrmp3sync fadein fadein0 fadein2 fadeio fadeio0 fadeio2 fadeout fadeout0 fadeout2 fixbrokenchromaupsampling fixluminance fliphorizontal flipvertical frameevaluate freezeframe gaussresize generalconvolution getchannel getchannels getmtmode getparity grayscale greyscale histogram horizontalreduceby2 imagereader imagesource imagewriter info interleave internalcache internalcachemt invert killaudio killvideo lanczos4resize lanczosresize layer letterbox levels limiter loop mask maskhs max merge mergeargb mergechannels mergechroma mergeluma mergergb messageclip min mixaudio monotostereo normalize null opendmlsource overlay peculiarblend pointresize pulldown reduceby2 resampleaudio resetmask reverse rgbadjust scriptclip segmentedavisource segmenteddirectshowsource selecteven selectevery selectodd selectrangeevery separatefields setmtmode sharpen showalpha showblue showfiveversions showframenumber showgreen showred showsmpte showtime sincresize skewrows spatialsoften spline16resize spline36resize spline64resize ssrc stackhorizontal stackvertical subtitle subtract supereq swapfields swapuv temporalsoften timestretch tone trim turn180 turnleft turnright tweak unalignedsplice utoy utoy8 version verticalreduceby2 vtoy vtoy8 wavsource weave writefile writefileend writefileif writefilestart ytouv", + [2] = "addgrain addgrainc agc_hdragc analyzelogo animeivtc asharp audiograph autocrop autoyuy2 avsrecursion awarpsharp bassaudiosource bicublinresize bifrost binarize blendfields blindpp blockbuster bordercontrol cfielddiff cframediff chromashift cnr2 colormatrix combmask contra convolution3d convolution3dyv12 dctfilter ddcc deblendlogo deblock deblock_qed decimate decomb dedup deen deflate degrainmedian depan depanestimate depaninterleave depanscenes depanstabilize descratch despot dfttest dgbob dgsource directshowsource distancefunction dss2 dup dupmc edeen edgemask ediupsizer eedi2 eedi3 eedi3_rpow2 expand faerydust fastbicubicresize fastbilinearresize fastediupsizer dedgemask fdecimate ffaudiosource ffdshow ffindex ffmpegsource ffmpegsource2 fft3dfilter fft3dgpu ffvideosource fielddeinterlace fielddiff fillmargins fity2uv fity2u fity2v fitu2y fitv2y fluxsmooth fluxsmoothst fluxsmootht framediff framenumber frfun3b frfun7 gicocu golddust gradfun2db grapesmoother greedyhma grid guavacomb hqdn3d hybridfupp hysteresymask ibob improvesceneswitch inflate inpand inpaintlogo interframe interlacedresize interlacedwarpedresize interleaved2planar iscombed iscombedt iscombedtivtc kerneldeint leakkernelbob leakkerneldeint limitedsharpen limitedsharpenfaster logic lsfmod lumafilter lumayv12 manalyse maskeddeinterlace maskedmerge maskedmix mblockfps mcompensate mctemporaldenoise mctemporaldenoisepp mdegrain1 mdegrain2 mdegrain3 mdepan medianblur mergehints mflow mflowblur mflowfps mflowinter minblur mipsmooth mmask moderatesharpen monitorfilter motionmask mpasource mpeg2source mrecalculate mscdetection msharpen mshow msmooth msu_fieldshiftfixer msu_frc msuper mt mt_adddiff mt_average mt_binarize mt_circle mt_clamp mt_convolution mt_deflate mt_diamond mt_edge mt_ellipse mt_expand mt_freeellipse mt_freelosange mt_freerectangle mt_hysteresis mt_infix mt_inflate mt_inpand mt_invert mt_logic mt_losange mt_lut mt_lutf mt_luts mt_lutspa mt_lutsx mt_lutxy mt_lutxyz mt_makediff mt_mappedblur mt_merge mt_motion mt_polish mt_rectangle mt_square mti mtsource multidecimate mvanalyse mvblockfps mvchangecompensate mvcompensate mvdegrain1 mvdegrain2 mvdegrain3 mvdenoise mvdepan mvflow mvflowblur mvflowfps mvflowfps2 mvflowinter mvincrease mvmask mvrecalculate mvscdetection mvshow nicac3source nicdtssource niclpcmsource nicmpasource nicmpg123source nnedi nnedi2 nnedi2_rpow2 nnedi3 nnedi3_rpow2 nomosmooth overlaymask peachsmoother pixiedust planar2interleaved qtgmc qtinput rawavsource rawsource reduceflicker reinterpolate411 removedirt removedust removegrain removegrainhd removetemporalgrain repair requestlinear reversefielddominance rgb3dlut rgdeinterlace rgsdeinterlace rgblut rotate sangnom seesaw sharpen2 showchannels showcombedtivtc smartdecimate smartdeinterlace smdegrain smoothdeinterlace smoothuv soothess soxfilter spacedust sshiq ssim ssiq stmedianfilter t3dlut tanisotropic tbilateral tcanny tcomb tcombmask tcpserver tcpsource tdecimate tdeint tedgemask telecide temporalcleaner temporalrepair temporalsmoother tfieldblank tfm tisophote tivtc tmaskblank tmaskedmerge tmaskedmerge3 tmm tmonitor tnlmeans tomsmocomp toon textsub ttempsmooth ttempsmoothf tunsharp unblock uncomb undot unfilter unsharpmask vaguedenoiser variableblur verticalcleaner videoscope vinverse vobsub vqmcalc warpedresize warpsharp xsharpen yadif yadifmod yuy2lut yv12convolution yv12interlacedreduceby2 yv12interlacedselecttopfields yv12layer yv12lut yv12lutxy yv12substract yv12torgb24 yv12toyuy2", + [3] = "abs apply assert bool ceil chr clip continueddenominator continuednumerator cos default defined eval averagechromau averagechromav averageluma chromaudifference chromavdifference lumadifference exist exp findstr float floor frac hexvalue import int isbool isclip isfloat isint isstring lcase leftstr load_stdcall_plugin loadcplugin loadplugin loadvfapiplugin loadvirtualdubplugin log midstr muldiv nop opt_allowfloataudio opt_avipadscanlines opt_dwchannelmask opt_usewaveextensible opt_vdubplanarhack pi pow rand revstr rightstr round scriptdir scriptfile scriptname select setmemorymax setplanarlegacyalignment rgbdifference rgbdifferencefromprevious rgbdifferencetonext udifferencefromprevious udifferencetonext setworkingdir sign sin spline sqrt string strlen time ucase undefined value versionnumber versionstring uplanemax uplanemedian uplanemin uplaneminmaxdifference vdifferencefromprevious vdifferencetonext vplanemax vplanemedian vplanemin vplaneminmaxdifference ydifferencefromprevious ydifferencetonext yplanemax yplanemedian yplanemin yplaneminmaxdifference", + [4] = "audiobits audiochannels audiolength audiolengthf audiorate framecount framerate frameratedenominator frameratenumerator getleftchannel getrightchannel hasaudio hasvideo height isaudiofloat isaudioint isfieldbased isframebased isinterleaved isplanar isrgb isrgb24 isrgb32 isyuv isyuy2 isyv12 width", + [5] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 32, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT: /* */"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["COMMENT: [* *]"] = { + id = 2, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["LINE COMMENT: #"] = { + id = 3, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["OPERATORS"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIERS"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DOUBLE QUOTED STRING"] = { + id = 7, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["STRING WITH THREE DOUBLE QUOTES"] = { + id = 8, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD"] = { + id = 9, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FILTER"] = { + id = 10, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PLUGIN"] = { + id = 11, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION"] = { + id = 12, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["CLIP PROPERTIES"] = { + id = 13, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["USER DEFINED"] = { + id = 14, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/baanc.lua b/src/NotepadNext/languages/baanc.lua new file mode 100644 index 000000000..06c098721 --- /dev/null +++ b/src/NotepadNext/languages/baanc.lua @@ -0,0 +1,174 @@ +local L = {} + +L.lexer = "baanc" + +L.singleLineComment = "// " + +L.extensions = { + "bc", + "cln", +} + +L.keywords = { + [0] = "alike all and array as asc at avg base based between boolean both break bset buffer by call case cast chart clear clearunref common const continue count cross current_date current_timestamp date date.num date.to.num debug default delete deleteempty deleteerror desc dim distinct dll dllusage domain double else empty end endcase enddelete enddllusage endfor endfunctionusage endif endselect endupdate endwhile enum_description eq escape exists extern false fatal fetching field first fixed for from full function functionusage ge global goto group gt having hint hints if in include index inner input inrange integer is join label last le leading left like long lt max mb menu message min multibyte ne no nodebug not notransactions nowarnings null on or order ordered outer path pi prepared print prompt question raw real ref reference refers repeat retry return right row rows select selectbind selectdo selectempty selecteos selecterror session set setunref size skip static step sticky stop strict_boolean string subhint sum table text_content then timestamp to trailing trim true union unref until update updateempty updateerror use used void warning warnings when where wherebind whereused while with", + [1] = "abort abort.io db.after.delete db.after.insert db.after.update xmlSetData zoom.to$", + [2] = "~.is.mandatory", + [3] = "after.choice: after.delete: after.display: after.field: after.form: after.group: after.input: after.layout: after.read: after.rewrite: after.skip.delete: after.skip.rewrite: after.skip.write: after.write: after.zoom: before.checks: before.choice: before.delete: before.display: before.field: before.form: before.group: before.input: before.layout: before.print: before.read: before.rewrite: before.write: before.zoom: check.input: domain.error: init.field: init.form: init.group: on.choice: on.entry: on.exit: on.input: read.view: ref.display: ref.input: selection.filter: when.field.changes:", + [4] = "after.~: before.~: choice.~: choice.abort.program: choice.abort.work: choice.add.set: choice.ask.helpinfo: choice.attachments: choice.bms: choice.calculator: choice.calender: choice.cancel.work: choice.change.frm: choice.change.order: choice.cmd.about.baan: choice.cmd.copy: choice.cmd.cut: choice.cmd.options: choice.cmd.paste: choice.cont.process: choice.create.job: choice.current.work: choice.cust.grid: choice.def.find: choice.display.set: choice.dupl.occur: choice.end.program: choice.field.browse: choice.field.help: choice.find.data: choice.first.frm: choice.first.set: choice.first.view: choice.freeze.columns: choice.get.defaults: choice.global.copy: choice.global.delete: choice.glossary: choice.help.index: choice.hide.fields: choice.interrupt: choice.last.frm: choice.last.set: choice.last.view: choice.mark.delete: choice.mark.occur: choice.modify.set: choice.next.frm: choice.next.set: choice.next.view: choice.next.work: choice.prev.frm: choice.prev.set: choice.prev.view: choice.print.data: choice.processes: choice.recover.set: choice.reference: choice.resize.frm: choice.rotate.curr: choice.run.job: choice.save.defaults: choice.select.all: choice.send.data: choice.sendto.desktop: choice.sendto.editor: choice.sendto.mail: choice.sendto.tasklst: choice.start.chart: choice.start.query: choice.start.set: choice.suspend.work: choice.switch.windows: choice.synchronize: choice.text.manager: choice.to.clipboard: choice.unfreeze.colum: choice.update.db: choice.user.0: choice.user.1: choice.user.2: choice.user.3: choice.user.4: choice.user.5: choice.user.6: choice.user.7: choice.user.8: choice.user.9: choice.using.help: choice.zoom: declaration: detail.~: field.~: footer.~: form.~: functions: group.~: header.~: main.table.io: on.display.total.line: on.error: zoom.from.~:", + [5] = "actual.occ zoomreturn$", + [6] = "__file__ z.session", + [7] = "^tcyesno. ^tdsls.corg.", + [8] = "dalnew dalupdate", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x808040), + bgColor = rgb(defaultBg), + fontStyle = 3, + }, + ["COMMENT DOC"] = { + id = 2, + fgColor = rgb(0x004000), + bgColor = rgb(0xFCFDDB), + fontStyle = 3, + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS"] = { + id = 4, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING"] = { + id = 5, + fgColor = rgb(0xFF0080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREPROCESSOR"] = { + id = 6, + fgColor = rgb(0x0000A0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATOR"] = { + id = 7, + fgColor = rgb(0x800040), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["STRING EOL NC"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(0xE0C0E0), + fontStyle = 3, + }, + ["FUNCTIONS"] = { + id = 10, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTIONS ABRIDGED"] = { + id = 11, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SUB SECTIONS"] = { + id = 12, + fgColor = rgb(0xFF4500), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MAIN SECTIONS"] = { + id = 13, + fgColor = rgb(0x800080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREDEFINED VARIABLE"] = { + id = 14, + fgColor = rgb(0x800040), + bgColor = rgb(0xA5EFF5), + fontStyle = 1, + }, + ["PREDEFINED ATTRIBUTES"] = { + id = 15, + fgColor = rgb(0xFF0080), + bgColor = rgb(0x98F3A4), + fontStyle = 1, + }, + ["ENUM DOMAINS"] = { + id = 16, + fgColor = rgb(OperatorColor), + bgColor = rgb(0xFFFF80), + fontStyle = 1, + }, + ["USER DEFINED"] = { + id = 17, + fgColor = rgb(0x800040), + bgColor = rgb(0x8AFFC5), + fontStyle = 1, + }, + ["TABLE DEFINITIONS"] = { + id = 18, + fgColor = rgb(0x9932CC), + bgColor = rgb(defaultBg), + fontStyle = 5, + }, + ["TABLE SQL"] = { + id = 19, + fgColor = rgb(0x8A2BE2), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DLL FUNCTIONS"] = { + id = 20, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DOMAIN DEFINITIONS"] = { + id = 21, + fgColor = rgb(0xB8860B), + bgColor = rgb(defaultBg), + fontStyle = 5, + }, + ["FUNCTION DEFINITIONS"] = { + id = 22, + fgColor = rgb(0xB22222), + bgColor = rgb(defaultBg), + fontStyle = 5, + }, + ["OBJECT DEFINITIONS"] = { + id = 23, + fgColor = rgb(0x8080FF), + bgColor = rgb(defaultBg), + fontStyle = 5, + }, + ["PREPROC DEFINITIONS"] = { + id = 24, + fgColor = rgb(0x556B2F), + bgColor = rgb(defaultBg), + fontStyle = 5, + }, +} +return L diff --git a/src/NotepadNext/languages/bash.lua b/src/NotepadNext/languages/bash.lua new file mode 100644 index 000000000..a0548234d --- /dev/null +++ b/src/NotepadNext/languages/bash.lua @@ -0,0 +1,106 @@ +local L = {} + +L.lexer = "bash" + +L.singleLineComment = "# " + +L.first_line = { + "^#!.*bash", + "^#!.*zsh", + "^#!.*csh", + "^#!.*bsh", + "^#!.*sh", +} + +L.extensions = { + "bash", + "sh", + "bsh", + "csh", + "bash_profile", + "bashrc", + "profile", +} + +L.keywords = { + [0] = "7z adduser alias apt-get ar as asa autoconf automake awk banner base64 basename bash bc bdiff blkid break bsdcpio bsdtar bunzip2 bzcmp bzdiff bzegrep bzfgrep bzgrep bzip2 bzip2recover bzless bzmore c++ cal calendar case cat cc cd cfdisk chattr chgrp chmod chown chroot chvt cksum clang clang++ clear cmp col column comm compgen compress continue convert cp cpio crontab crypt csplit ctags curl cut date dc dd deallocvt declare deluser depmod deroff df dialog diff diff3 dig dircmp dirname disown dmesg do done dpkg dpkg-deb du echo ed egrep elif else env esac eval ex exec exit expand export expr fakeroot false fc fdisk ffmpeg fgrep fi file find flex flock fmt fold for fsck function functions fuser fusermount g++ gas gawk gcc gdb genisoimage getconf getopt getopts git gpg gpgsplit gpgv grep gres groff groups gunzip gzexe hash hd head help hexdump hg history httpd iconv id if ifconfig ifdown ifquery ifup in insmod integer inxi ip ip6tables ip6tables-save ip6tables-restore iptables iptables-save iptables-restore ip jobs join kill killall killall5 lc ld ldd let lex line ln local logname look ls lsattr lsb_release lsblk lscpu lshw lslocks lsmod lsusb lzcmp lzegrep lzfgrep lzgrep lzless lzma lzmainfo lzmore m4 mail mailx make man mkdir mkfifo mkswap mktemp modinfo modprobe mogrify more mount msgfmt mt mv nameif nasm nc ndisasm netcat newgrp nl nm nohup ntps objdump od openssl p7zip pacman passwd paste patch pathchk pax pcat pcregrep pcretest perl pg ping ping6 pivot_root poweroff pr print printf ps pwd python python2 python3 ranlib read readlink readonly reboot reset return rev rm rmdir rmmod rpm rsync sed select service set sh sha1sum sha224sum sha256sum sha3sum sha512sum shift shred shuf shutdown size sleep sort spell split start stop strings strip stty su sudo sum suspend switch_root sync systemctl tac tail tar tee test then time times touch tr trap troff true tsort tty type typeset ulimit umask umount unalias uname uncompress unexpand uniq unlink unlzma unset until unzip unzipsfx useradd userdel uudecode uuencode vi vim wait wc wget whence which while who wpaste wstart xargs xdotool xxd xz xzcat xzcmp xzdiff xzfgrep xzgrep xzless xzmore yes yum zcat zcmp zdiff zegrep zfgrep zforce zgrep zless zmore znew zsh", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["ERROR"] = { + id = 1, + fgColor = rgb(defaultBg), + bgColor = rgb(0xFF0000), + }, + ["INSTRUCTION WORD"] = { + id = 4, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 5, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 7, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["SCALAR"] = { + id = 9, + fgColor = rgb(0xFF8040), + bgColor = rgb(0xFFFFD9), + fontStyle = 1, + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PARAM"] = { + id = 10, + fgColor = rgb(0x008080), + bgColor = rgb(0x00FFFF), + }, + ["BACKTICKS"] = { + id = 11, + fgColor = rgb(0x804040), + bgColor = rgb(0xE1FFF3), + fontStyle = 1, + }, + ["HERE DELIM"] = { + id = 12, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + fontStyle = 1, + }, + ["HERE Q"] = { + id = 13, + fgColor = rgb(0xFF0000), + bgColor = rgb(0xFFFF80), + }, +} +return L diff --git a/src/NotepadNext/languages/batch.lua b/src/NotepadNext/languages/batch.lua new file mode 100644 index 000000000..6b1b7d016 --- /dev/null +++ b/src/NotepadNext/languages/batch.lua @@ -0,0 +1,63 @@ +local L = {} + +L.lexer = "batch" + +L.singleLineComment = "REM " + +L.extensions = { + "bat", + "cmd", + "nt", +} + +L.keywords = { + [0] = "assoc aux break call cd chcp chdir choice cls cmdextversion color com com1 com2 com3 com4 con copy country ctty date defined del dir do dpath echo else endlocal erase errorlevel exist exit for ftype goto if in loadfix loadhigh lpt lpt1 lpt2 lpt3 lpt4 md mkdir move not nul path pause popd prn prompt pushd rd rem ren rename rmdir set setlocal shift start time title type ver verify vol", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["KEYWORDS"] = { + id = 2, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["LABEL"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(0xFFFF80), + fontStyle = 1, + }, + ["HIDE SYMBOL"] = { + id = 4, + fgColor = rgb(0xFF00FF), + bgColor = rgb(defaultBg), + }, + ["COMMAND"] = { + id = 5, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["VARIABLE"] = { + id = 6, + fgColor = rgb(0xFF8000), + bgColor = rgb(0xFCFFF0), + fontStyle = 1, + }, + ["OPERATOR"] = { + id = 7, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/blitzbasic.lua b/src/NotepadNext/languages/blitzbasic.lua new file mode 100644 index 000000000..6b3f16a65 --- /dev/null +++ b/src/NotepadNext/languages/blitzbasic.lua @@ -0,0 +1,90 @@ +local L = {} + +L.lexer = "blitzbasic" + +L.singleLineComment = "; " + +L.extensions = { + "bb", +} + +L.keywords = { + [0] = "abs accepttcpstream acos after and apptitle asc asin atan atan2 automidhandle autosuspend availvidmem backbuffer banksize before bin calldll case ceil changedir channelpan channelpitch channelplaying channelvolume chr closedir closefile closemovie closetcpserver closetcpstream closeudpstream cls clscolor color colorblue colorgreen colorred commandline const copybank copyfile copyimage copypixel copypixelfast copyrect copystream cos countgfxdrivers countgfxmodes counthostips createbank createdir createimage createnetplayer createprocess createtcpserver createtimer createudpstream currentdate currentdir currenttime data debuglog default delay delete deletedir deletefile deletenetplayer desktopbuffer dim dottedip drawblock drawblockrect drawimage drawimagerect drawmovie each else else if elseif end end function end if end select end type endgraphics endif eof execfile exit exp false field filepos filesize filetype first flip float floor flushjoy flushkeys flushmouse fontheight fontname fontsize fontstyle fontwidth for forever freebank freefont freeimage freesound freetimer frontbuffer function gammablue gammagreen gammared getcolor getenv getkey getmouse gfxdrivername gfxmodedepth gfxmodeexists gfxmodeformat gfxmodeheight gfxmodewidth global gosub goto grabimage graphics graphicsbuffer graphicsdepth graphicsformat graphicsheight graphicswidth handleimage hex hidepointer hostip hostnetgame if imagebuffer imageheight imagerectcollide imagerectoverlap imagescollide imagesoverlap imagewidth imagexhandle imageyhandle include input insert instr int joinnetgame joydown joyhat joyhit joypitch joyroll joytype joyu joyudir joyv joyvdir joyx joyxdir joyy joyyaw joyydir joyz joyzdir keydown keyhit keywait last left len line loadanimimage loadbuffer loadfont loadimage loadsound local lockbuffer lockedformat lockedpitch lockedpixels log log10 loopsound lower lset maskimage mid midhandle millisecs mod morefiles mousedown mousehit mousex mousexspeed mousey mouseyspeed mousez mousezspeed movemouse movieheight movieplaying moviewidth netmsgdata netmsgfrom netmsgto netmsgtype netplayerlocal netplayername new next nextfile not null openfile openmovie opentcpstream or origin oval pausechannel pausetimer peekbyte peekfloat peekint peekshort pi playcdtrack playmusic playsound plot pokebyte pokefloat pokeint pokeshort print queryobject rand read readavail readbyte readbytes readdir readfile readfloat readint readline readpixel readpixelfast readshort readstring rect rectsoverlap recvnetmsg recvudpmsg repeat replace resettimer resizebank resizeimage restore resumechannel resumetimer return right rnd rndseed rotateimage rset runtimeerror sar savebuffer saveimage scaleimage scanline seedrnd seekfile select sendnetmsg sendudpmsg setbuffer setenv setfont setgamma setgfxdriver sgn shl showpointer shr sin soundpan soundpitch soundvolume sqr startnetgame step stop stopchannel stopnetgame str string stringheight stringwidth systemproperty tan tcpstreamip tcpstreamport tcptimeouts text tformfilter tformimage then tileblock tileimage timerticks to totalvidmem trim true type udpmsgip udpmsgport udpstreamip udpstreamport udptimeouts unlockbuffer until updategamma upper viewport vwait waitkey waitmouse waittimer wend while write writebyte writebytes writefile writefloat writeint writeline writepixel writepixelfast writeshort writestring xor", + [1] = "None", + [2] = "None", + [3] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD1"] = { + id = 3, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 4, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEYWORD2"] = { + id = 10, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD3"] = { + id = 11, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD4"] = { + id = 12, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 15, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["ERROR"] = { + id = 16, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["HEXNUMBER"] = { + id = 17, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["BINNUMBER"] = { + id = 18, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/c.lua b/src/NotepadNext/languages/c.lua new file mode 100644 index 000000000..8541de356 --- /dev/null +++ b/src/NotepadNext/languages/c.lua @@ -0,0 +1,118 @@ +local L = {} + +L.lexer = "cpp" + +L.singleLineComment = "// " + +L.extensions = { + "c", + "lex", +} + +L.keywords = { + [0] = "if else switch case default break goto return for while do continue typedef sizeof offsetof alignof _Alignof _Generic _Static_assert and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq NULL", + [1] = "void struct union enum char short int long double float signed unsigned const static extern auto register volatile restrict _Atomic bool _Bool complex _Complex imaginary _Imaginary inline noreturn _Noreturn alignas _Alignas thread_local _Thread_local uint8_t uint16_t uint32_t uint64_t int8_t int16_t int32_t int64_t uint_least8_t uint_least16_t uint_least32_t uint_least64_t int_least8_t int_least16_t int_least32_t int_least64_t uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t int_fast8_t int_fast16_t int_fast32_t int_fast64_t uintptr_t intptr_t uintmax_t intmax_t ptrdiff_t max_align_t div_t ldiv_t lldiv_t imaxdiv_t size_t time_t clock_t wchar_t char16_t char32_t sig_atomic_t FILE", +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT"] = { + id = 23, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT DOC"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/caml.lua b/src/NotepadNext/languages/caml.lua new file mode 100644 index 000000000..0d71fe9ab --- /dev/null +++ b/src/NotepadNext/languages/caml.lua @@ -0,0 +1,98 @@ +local L = {} + +L.lexer = "caml" + +L.extensions = { + "ml", + "mli", + "sml", + "thy", +} + +L.keywords = { + [0] = "and as assert asr begin class constraint do done downto else end exception external false for fun function functor if in include inherit initializer land lazy let lor lsl lsr lxor match method mod module mutable new object of open or private rec sig struct then to true try type val virtual when while with", + [1] = "option Some None ignore ref lnot succ pred", + [2] = "array bool char float int list string unit", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 1, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["TAGNAME"] = { + id = 2, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 3, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["BUILIN FUNC & TYPE"] = { + id = 4, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["TYPE"] = { + id = 5, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["LINENUM"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATOR"] = { + id = 7, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 8, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 9, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 11, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 12, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 13, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 14, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/cmake.lua b/src/NotepadNext/languages/cmake.lua new file mode 100644 index 000000000..eda83db3a --- /dev/null +++ b/src/NotepadNext/languages/cmake.lua @@ -0,0 +1,104 @@ +local L = {} + +L.lexer = "cmake" + +L.singleLineComment = "# " + +L.extensions = { + "cmake", +} + +L.keywords = { + [0] = "add_custom_command add_compile_definitions add_compile_options add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_link_options add_subdirectory add_test aux_source_directory build_command build_name cmake_minimum_required configure_file create_test_sourcelist else elseif enable_language enable_testing endforeach endfunction endif endmacro endwhile exec_program execute_process export export_library_dependencies file find_file find_library find_package find_path find_program fltk_wrap_ui foreach function get_cmake_property get_directory_property get_filename_component get_source_file_property get_target_property get_test_property if include include_directories include_external_msproject include_regular_expression install install_files install_programs install_targets link_directories link_libraries list load_cache load_command macro make_directory mark_as_advanced math message option output_required_files project qt_wrap_cpp qt_wrap_ui remove remove_definitions separate_arguments set set_directory_properties set_source_files_properties set_target_properties set_tests_properties site_name source_group string subdir_depends subdirs target_compile_definitions target_compile_features target_compile_options target_include_directories target_link_directories target_link_libraries target_link_options target_sources try_compile try_run use_mangled_mesa utility_source variable_requires vtk_make_instantiator vtk_wrap_java vtk_wrap_python vtk_wrap_tcl while write_file", + [2] = "ABSOLUTE ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ALL AND APPEND ARGS ASCII BEFORE CACHE CACHE_VARIABLES CLEAR COMMAND COMMANDS COMMAND_NAME COMMENT COMPARE COMPILE_FLAGS COPYONLY DEFINED DEFINE_SYMBOL DEPENDS DOC EQUAL ESCAPE_QUOTES EXCLUDE EXCLUDE_FROM_ALL EXISTS EXPORT_MACRO EXT EXTRA_INCLUDE FATAL_ERROR FILE FILES FORCE FUNCTION GENERATED GLOB GLOB_RECURSE GREATER GROUP_SIZE HEADER_FILE_ONLY HEADER_LOCATION IMMEDIATE INCLUDES INCLUDE_DIRECTORIES INCLUDE_INTERNALS INCLUDE_REGULAR_EXPRESSION LESS LINK_DIRECTORIES LINK_FLAGS LOCATION MACOSX_BUNDLE MACROS MAIN_DEPENDENCY MAKE_DIRECTORY MATCH MATCHALL MATCHES MODULE NAME NAME_WE NOT NOTEQUAL NO_SYSTEM_PATH OBJECT_DEPENDS OPTIONAL OR OUTPUT OUTPUT_VARIABLE PATH PATHS POST_BUILD POST_INSTALL_SCRIPT PREFIX PREORDER PRE_BUILD PRE_INSTALL_SCRIPT PRE_LINK PROGRAM PROGRAM_ARGS PROPERTIES QUIET RANGE READ REGEX REGULAR_EXPRESSION REPLACE REQUIRED RETURN_VALUE RUNTIME_DIRECTORY SEND_ERROR SHARED SOURCES STATIC STATUS STREQUAL STRGREATER STRLESS SUFFIX TARGET TOLOWER TOUPPER VAR VARIABLES VERSION WIN32 WRAP_EXCLUDE WRITE APPLE MINGW MSYS CYGWIN BORLAND WATCOM MSVC MSVC_IDE MSVC60 MSVC70 MSVC71 MSVC80 CMAKE_COMPILER_2005 OFF ON", + [3] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["STRING D"] = { + id = 2, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING L"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["STRING R"] = { + id = 4, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 4, + }, + ["COMMAND"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PARAMETER"] = { + id = 6, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["VARIABLE"] = { + id = 7, + fgColor = rgb(0xFF8040), + bgColor = rgb(defaultBg), + }, + ["USER DEFINED"] = { + id = 8, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["WHILEDEF"] = { + id = 9, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FOREACHDEF"] = { + id = 10, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IFDEF"] = { + id = 11, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MACRODEF"] = { + id = 12, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING VARIABLE"] = { + id = 13, + fgColor = rgb(0x808080), + bgColor = rgb(0xFEFCF5), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 14, + fgColor = rgb(0x804040), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/cobol.lua b/src/NotepadNext/languages/cobol.lua new file mode 100644 index 000000000..b1c4334d4 --- /dev/null +++ b/src/NotepadNext/languages/cobol.lua @@ -0,0 +1,105 @@ +local L = {} + +L.lexer = "cobol" + +L.singleLineComment = "* " + +L.extensions = { + "cbl", + "cbd", + "cdb", + "cdc", + "cob", + "cpy", + "copy", + "lst", +} + +L.keywords = { + [0] = "configuration data declaratives division environment file file-control function function-id i-o i-o-control identification input input-output linkage local-storage output procedure program program-id screen section special-names working-storage exec end-exec", + [1] = "accept add allocate alter call cancel close commit compute continue delete destroy disable display divide enable entry evaluate also when exit free generate go to goback if else initialize initiate inquire invoke inspect merge modify move multiply next sentence open perform purge raise read ready receive release reset resume return rewrite rollback search send set sort start stop string subtract suppress terminate transform unlock unstring use validate write end-accept end-add end-call end-compute end-delete end-display end-divide end-evaluate end-if end-multiply end-of-page end-perform end-read end-receive end-return end-rewrite end-search end-start end-string end-subtract end-unstring end-write copy replace abs acos annuity asin atan boolean-of-integer byte-length char char-national combined-datetime concatenate cos currency-symbol current-date date-of-integer date-to-yyyymmdd day-of-integer day-to-yyyyddd display-of e exception-file exception-file-n exception-location exception-location-n exception-statement exception-status exp exp10 factorial formatted-current-date formatted-date formatted-datetime formatted-time fraction-part highest-algebraic integer integer-of-boolean integer-of-date integer-of-day integer-of-formatted-date integer-part length length-an locale-compare locale-date locale-time locale-time-from-seconds log log10 lower-case lowest-algebraic max mean median midrange min mod module-caller-id module-date module-formatted-date module-id module-path module-source module-time monetary-decimal-point monetary-thousands-separator national-of numeric-decimal-point numeric-thousands-separator numval numval-c numval-f ord ord-max ord-min pi present-value random range rem reverse seconds-from-formatted-time seconds-past-midnight sign sin sqrt standard-compare standard-deviation stored-char-length substitute substitute-case sum tan test-date-yyyymmdd test-day-yyyyddd test-formatted-datetime test-numval test-numval-c test-numval-f trim upper-case variance when-compiled year-to-yyyy", + [2] = "high-value high-values low-value low-values space spaces quote quotes zero zeroes zeros author date-compiled date-modified date-written installation remarks security cob-crt-status debug-item debug-line debug-name debug-sub-1 debug-sub-2 debug-sub-3 debug-contents number-of-call-parameters return-code return-code-unsigned sort-return tally dialect-all jnienvptr json-code linage-counter shift-in shift-out sort-control sort-core-size sort-file-size sort-message sort-mode-size xml-code xml-event xml-information xml-namespace xml-namespace-prefix xml-nnamespace xml-nnamespace-prefix xml-ntext xml-text sysin sysipt stdin sysout syslist syslst stdout print printer printer-1 syserr stderr console c01 c02 c03 c04 c05 c06 c07 c08 c09 c10 c11 c12 csp formfeed call-convention switch-0 switch-1 switch-2 switch-3 switch-4 switch-5 switch-6 switch-7 switch-8 switch-9 switch-10 switch-11 switch-12 switch-13 switch-14 switch-15 switch-16 switch-17 switch-18 switch-19 switch-20 switch-21 switch-22 switch-23 switch-24 switch-25 switch-26 switch-27 switch-28 switch-29 switch-30 switch-31 switch-32 switch-33 switch-34 switch-35 switch-36 upsi-0 upsi-1 upsi-2 upsi-3 upsi-4 upsi-5 upsi-6 upsi-7 access active-class address advancing after aligned all alphabet alphabetic alphabetic-lower alphabetic-upper alphanumeric alphanumeric-edited alternate and any anycase are area areas as ascending assign at automatic b-and b-not b-or b-xor based before binary binary-char binary-double binary-long binary-sequential binary-short bit blank block boolean bottom by cd cf ch character characters class class-id clock-units code-set col collating cols column columns comma common communication comp comp-3 comp-5 computational computational-3 computational-5 condition constant contains content control controls converting corr corresponding count crt currency cursor data-pointer date day day-of-week de debugging decimal-point default delimited delimiter depending descending destination detail down duplicates dynamic ec egi emi end enter eo eop equal equals error esi every exception exception-object exclusive extend external factory false farthest-from-zero fd filler final first float-binary-128 float-binary-32 float-binary-64 float-decimal-16 float-decimal-34 float-extended float-infinity float-long float-not-a-number-quiet float-not-a-number-signaling float-short footing for format from function-pointer get giving global greater group group-usage heading in in-arithmetic-range index indexed indicate inherits initial initialized interface interface-id into invalid is just justified key label last leading left less limit limits linage line line-counter line-sequential lines locale lock manual message method method-id minus mode modules multiple national national-edited native nearest-to-zero negative negative-infinity nested no not null number numbers numeric numeric-edited object object-computer object-reference occurs of off omitted on only optional options or order organization other overflow override packed-decimal padding page page-counter pf ph physical pic picture plus pointer position positive positive-infinity present previous printing procedures proceed program-pointer property prototype queue raising rd record records redefines reel reference references relative remainder removal renames replacing report reporting reports repository rerun reserve retry returning reversed rewind rf rh right rounded run same sd segment segment-limit select self separate sequence sequential sharing signed size sort-merge source source-computer sources standard standard-1 standard-2 status step sub-queue-1 sub-queue-2 sub-queue-3 super symbolic sync synchronized system-default table tallying terminal test text than then through thru time times top trailing true type typedef unit universal unsigned until up upon usage user-default using val-status valid validate-status value values varying with words arithmetic attribute auto away-from-zero background-color bell binary-c-long binary-encoding blink capacity center chaining classification cobol comp-1 comp-4 comp-6 comp-x computational-1 computational-4 computational-6 computational-x cycle decimal-encoding entry-convention eol eos erase expands float-binary float-decimal float-not-a-number foreground-color forever full high-order-left high-order-right highlight ignoring implements intermediate intrinsic lc_all lc_collate lc_ctype lc_messages lc_monetary lc_numeric lc_time lowlight memory nearest-away-from-zero nearest-even-intermediate nearest-toward-zero none normal paragraph prefixed prohibited recursive relation required reverse-video rounding seconds secure short standard-binary standard-decimal statement strong structure symbol tape toward-greater toward-lesser truncation ucs-4 underline utf-16 utf-8 yyyyddd yyyymmdd 3-d apply background background-high background-low bar blob bold box busy cbl clob combo-box dbclob dbcs draw drop grid grip high hot-track hscroll hscroll-pos id imp kanji low num-rows o-fill oostackptr pos prompt public rowid scroll scroll-bar shadow skip1 skip2 skip3 sql tab track-thumb unbounded variant virtual-width vscroll vscroll-bar vscroll-pos wait width wrap xml", +} + +L.styles = { + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DECLARATION"] = { + id = 5, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["INSTRUCTION WORD"] = { + id = 16, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD"] = { + id = 8, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/coffeescript.lua b/src/NotepadNext/languages/coffeescript.lua new file mode 100644 index 000000000..d3a147636 --- /dev/null +++ b/src/NotepadNext/languages/coffeescript.lua @@ -0,0 +1,126 @@ +local L = {} + +L.lexer = "coffeescript" + +L.singleLineComment = "# " + +L.extensions = { + "coffee", + "litcoffee", +} + +L.keywords = { + [0] = "new instanceof do return break continue throw for while until loop if else unless switch when then in of by typeof delete where try catch finally prototype jQuery case default function var void with const let enum export import native __hasProp __extends __slice __bind __indexOf", + [1] = "Object Number Boolean Array String RegExp Function Date Math eval setInterval clearInterval setTimeout clearTimeout isFinite isNaN parseFloat parseInt escape unescape console encodeURI encodeURIComponent decodeURI decodeURIComponent window document navigator location history screen alert prompt process GLOBAL require exports", + [3] = "false true yes no on off undefined null NaN Infinity", +} + +L.styles = { + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREDEFINED CONSTANT"] = { + id = 19, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT BLOCK"] = { + id = 22, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["VERBOSE REGEX"] = { + id = 23, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 3, + }, + ["VERBOSE REGEX COMMENT"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/cpp.lua b/src/NotepadNext/languages/cpp.lua new file mode 100644 index 000000000..f96d8096d --- /dev/null +++ b/src/NotepadNext/languages/cpp.lua @@ -0,0 +1,138 @@ +local L = {} + +L.lexer = "cpp" + +L.singleLineComment = "// " + +L.extensions = { + "cpp", + "cxx", + "cc", + "h", + "hh", + "hpp", + "hxx", + "ino", +} + +L.properties = { + ["fold.cpp.comment.explicit"] = "0", + ["lexer.cpp.track.preprocessor"] = "0", + ["lexer.cpp.escape.sequence"] = "1", +} + +L.keywords = { + [0] = "alignof and and_eq bitand bitor break case catch compl const_cast continue default delete do dynamic_cast else false for goto if namespace new not not_eq nullptr operator or or_eq reinterpret_cast return sizeof static_assert static_cast switch this throw true try typedef typeid using while xor xor_eq NULL", + [1] = "alignas asm auto bool char char16_t char32_t class clock_t concept const consteval constexpr constinit decltype double enum explicit export extern final float friend inline int int8_t int16_t int32_t int64_t int_fast8_t int_fast16_t int_fast32_t int_fast64_t intmax_t intptr_t long mutable noexcept override private protected ptrdiff_t public register requires short signed size_t ssize_t static struct template thread_local time_t typename uint8_t uint16_t uint32_t uint64_t uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t uintmax_t uintptr_t union unsigned virtual void volatile wchar_t", + [2] = "a addindex addtogroup anchor arg attention author authors b brief bug c callergraph callgraph category cite class code cond copybrief copydetails copydoc copyright date def defgroup deprecated details diafile dir docbookonly dontinclude dot dotfile e else elseif em endcode endcond enddocbookonly enddot endhtmlonly endif endinternal endlatexonly endlink endmanonly endmsc endparblock endrtfonly endsecreflist enduml endverbatim endxmlonly enum example exception extends f$ f[ f] file fn f{ f} headerfile hidecallergraph hidecallgraph hideinitializer htmlinclude htmlonly idlexcept if ifnot image implements include includelineno ingroup interface internal invariant latexinclude latexonly li line link mainpage manonly memberof msc mscfile n name namespace nosubgrouping note overload p package page par paragraph param parblock post pre private privatesection property protected protectedsection protocol public publicsection pure ref refitem related relatedalso relates relatesalso remark remarks result return returns retval rtfonly sa secreflist section see short showinitializer since skip skipline snippet startuml struct subpage subsection subsubsection tableofcontents test throw throws todo tparam typedef union until var verbatim verbinclude version vhdlflow warning weakgroup xmlonly xrefitem", + [5] = "FIXME TODO XXX HACK NOTE", +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT"] = { + id = 23, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT DOC"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["TASK MARKER"] = { + id = 26, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/cs.lua b/src/NotepadNext/languages/cs.lua new file mode 100644 index 000000000..d3e5321c3 --- /dev/null +++ b/src/NotepadNext/languages/cs.lua @@ -0,0 +1,117 @@ +local L = {} + +L.lexer = "cpp" + +L.singleLineComment = "// " + +L.extensions = { + "cs", +} + +L.keywords = { + [0] = "abstract add alias as ascending async await base break case catch checked continue default delegate descending do dynamic else event explicit extern false finally fixed for foreach from get global goto group if implicit in interface internal into is join let lock namespace new null object operator orderby out override params partial private protected public readonly ref remove return sealed select set sizeof stackalloc switch this throw true try typeof unchecked unsafe using value virtual where while yield", + [1] = "bool byte char class const decimal double enum float int long sbyte short static string struct uint ulong ushort var void", +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT"] = { + id = 23, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT DOC"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/csound.lua b/src/NotepadNext/languages/csound.lua new file mode 100644 index 000000000..378878a60 --- /dev/null +++ b/src/NotepadNext/languages/csound.lua @@ -0,0 +1,103 @@ +local L = {} + +L.lexer = "csound" + +L.singleLineComment = "; " + +L.extensions = { + "orc", + "sco", + "csd", +} + +L.keywords = { + [0] = "a i db in or zr Add Dec Div Inc Mul Sub abs and cos dam dec div exp fin fof fog inh ino inq ins int inx inz lfo log mac mod mul not out pan pow rms rnd shl sin sqr sub sum tab tan tb0 tb1 tb2 tb3 tb4 tb5 tb6 tb7 tb8 tb9 urd vco xin xor zar zaw zir ziw zkr zkw adsr babo buzz cent clip comb cosh diff divz fini fink fmb3 fof2 fold fout frac ftsr gain goto in32 inch init line maca moog mute nrpn outc outh outo outq outs outx outz peak port pset pvoc rand seed sinh sqrt stix tabw tanh tb10 tb11 tb12 tb13 tb14 tb15 tone vadd vco2 vdiv vexp vibr vmap vmul vpow wrap xout xyin zacl zarg zawm ziwm zkcl zkwm FLbox FLjoy FLrun adsyn ampdb atone birnd bqrez butbp butbr buthp butlp clear ctrl7 dbamp dconv delay dumpk endin endop event expon fouti foutk ftgen ftlen gauss gbuzz grain guiro igoto ihold instr integ kgoto limit linen log10 loopg loopl lpf18 madsr max_k metro noise nsamp oscil out32 outch outic outkc outq1 outq2 outq3 outq4 outs1 outs2 pareq pitch pluck portk print pvadd randh randi rbjeq readk reson rezzy rnd31 scans scanu sense space tab_i table tbvcf tempo timek times tival tonek tonex vaddv vbap4 vbap8 vbapz vcomb vcopy vdecr vdivv veloc vexpv vibes vincr vmult voice vport vpowv vpvoc vsubv vwrap wgbow xadsr zamod zkmod FLhide FLkeyb FLknob FLpack FLshow FLtabs FLtext active adsynt alpass areson atonek atonex bamboo bbcutm bbcuts biquad cabasa cauchy cggoto cigoto ckgoto clfilt cngoto convle cosinv cpsoct cpspch cpstun cpuprc cross2 crunch ctrl14 ctrl21 delay1 delayk delayr delayw deltap denorm diskin dumpk2 dumpk3 dumpk4 envlpx expseg filesr fiopen fmbell follow foscil foutir ftlen2 ftload ftmorf ftsave grain2 grain3 harmon hrtfer initc7 interp jitter linenr lineto linseg locsig loopge loople lorenz loscil lowres lpread lpslot mandel mandol mclock mdelay midic7 midiin midion mirror moscil mpulse mrtmsg mxadsr nlfilt noteon notnum ntrpol octave octcps octpch opcode oscbnk oscil1 oscil3 oscili osciln oscils oscilx outiat outipb outipc outkat outkpb outkpc pchoct phasor planet poscil printk prints pvread pvsftr pvsftw random readk2 readk3 readk4 reinit resonk resonr resonx resony resonz reverb rigoto s16b14 s32b14 sekere sfload sfplay shaker sininv spat3d spdist spsend strset table3 tablei tablew tabw_i taninv tigoto timout turnon upsamp vbap16 vcella vco2ft vdel_k vdelay vlimit vmultv vrandh vrandi wgclar xscans xscanu FLcolor FLcount FLgroup FLlabel FLpanel FLvalue aftouch ampdbfs ampmidi aresonk balance bexprnd biquada changed clockon cps2pch cpsmidi cpstmid cpstuni cpsxpch dbfsamp dcblock deltap3 deltapi deltapn deltapx dispfft display envlpxr exprand expsega expsegr filelen filter2 flanger fmmetal fmrhode fmvoice follow2 foscili fprints ftchnls ftloadk ftlptim ftsavek gogobel granule hilbert initc14 initc21 invalue jitter2 jspline linrand linsegr locsend logbtwo loopseg loscil3 lowresx lphasor lposcil lpreson lpshold marimba massign midic14 midic21 midichn midion2 midiout moogvcf noteoff nreverb nstrnum octmidi oscil1i outic14 outipat outkc14 outkpat pcauchy pchbend pchmidi phaser1 phaser2 pinkish poisson polyaft poscil3 printk2 printks product pvcross pvsanal pvsinfo pvsynth randomh randomi release repluck reverb2 rspline rtclock seqtime sfilist sfinstr sfplay3 sfplaym sfplist slider8 sndwarp soundin spat3di spat3dt specsum streson tableiw tablekt tableng tablera tablewa taninv2 tempest tlineto transeg trigger trigseq trirand turnoff unirand valpass vco2ift vdelay3 vdelayk vdelayx vexpseg vibrato vlinseg vlowres vmirror waveset weibull wgbrass wgflute wgpluck wguide1 wguide2 xtratim zakinit FLbutton FLcolor2 FLprintk FLroller FLscroll FLsetBox FLsetVal FLslider FLupdate betarand butterbp butterbr butterhp butterlp chanctrl clockoff convolve cpsmidib ctrlinit cuserrnd deltapxw distort1 downsamp duserrnd filepeak fmpercfl fmwurlie fprintks hsboscil lowpass2 lpfreson lpinterp lposcil3 maxalloc midictrl multitap nestedap octmidib oscilikt outvalue pchmidib powoftwo prealloc pvinterp pvsadsyn pvscross pvsfread pvsmaska rireturn samphold schedule semitone sensekey setksmps sfinstr3 sfinstrm sfplay3m sfpreset slider16 slider32 slider64 slider8f soundout specaddm specdiff specdisp specfilt spechist specptrk specscal spectrum sprintks subinstr svfilter tablegpw tableikt tablemix tableseg tablewkt tablexkt tb0_init tb1_init tb2_init tb3_init tb4_init tb5_init tb6_init tb7_init tb8_init tb9_init tempoval vco2init vdelayxq vdelayxs vdelayxw vecdelay wgpluck2 wterrain xscanmap zfilter2 FLbutBank FLgetsnap FLpackEnd FLprintk2 FLsetFont FLsetSize FLsetText FLsetsnap FLslidBnk FLtabsEnd dripwater eventname ktableseg noteondur osciliktp oscilikts pgmassign phasorbnk pitchamdf pvbufread readclock sandpaper scantable schedwhen sfinstr3m sfpassign slider16f slider32f slider64f sndwarpst soundoutc soundouts tablecopy tableigpw tableimix tablexseg tb10_init tb11_init tb12_init tb13_init tb14_init tb15_init timeinstk timeinsts vbap4move vbap8move vbapzmove vdelayxwq vdelayxws xscansmap FLgroupEnd FLloadsnap FLpack_end FLpanelEnd FLsavesnap FLsetAlign FLsetColor FLsetVal_i FLtabs_end filenchnls noteondur2 scanhammer schedkwhen tableicopy tambourine vbap16move vbaplsinit wgbowedbar FLgroup_end FLpanel_end FLscrollEnd FLsetColor2 mididefault midinoteoff sleighbells FLscroll_end subinstrinit FLsetPosition FLsetTextSize FLsetTextType midinoteoncps midinoteonkey midinoteonoct midinoteonpch midipitchbend schedwhenname FLsetTextColor schedkwhenname midicontrolchange midiprogramchange midipolyaftertouch midichannelaftertouch", + [1] = "sr kr ar ksmps nchnls", + [2] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x669999), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0x339933), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 3, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTR"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["OPCODE"] = { + id = 6, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["HEADER STATEMENT"] = { + id = 7, + fgColor = rgb(0xCC2200), + bgColor = rgb(defaultBg), + }, + ["USER KEYWORDS"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT BLOCK"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["PARAMETER"] = { + id = 10, + fgColor = rgb(0x660099), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["A-RATE VARIABLE"] = { + id = 11, + fgColor = rgb(0x660099), + bgColor = rgb(defaultBg), + }, + ["K-RATE VARIABLE"] = { + id = 12, + fgColor = rgb(0x660099), + bgColor = rgb(defaultBg), + }, + ["I-RATE VARIABLE"] = { + id = 13, + fgColor = rgb(0x660099), + bgColor = rgb(defaultBg), + }, + ["GLOBAL VARIABLE"] = { + id = 14, + fgColor = rgb(0x660099), + bgColor = rgb(defaultBg), + }, + ["END OF LINE WHERE STRING IS NOT CLOSED"] = { + id = 15, + fgColor = rgb(defaultFg), + bgColor = rgb(0xE0C0E0), + }, +} +return L diff --git a/src/NotepadNext/languages/css.lua b/src/NotepadNext/languages/css.lua new file mode 100644 index 000000000..efba372c6 --- /dev/null +++ b/src/NotepadNext/languages/css.lua @@ -0,0 +1,87 @@ +local L = {} + +L.lexer = "css" + +L.extensions = { + "css", +} + +L.keywords = { + [0] = "-khtml-background-clip -khtml-background-origin -khtml-background-size -khtml-border-bottom-left-radius -khtml-border-bottom-right-radius -khtml-border-radius -khtml-border-top-left-radius -khtml-border-top-right-radius -khtml-opacity -moz-animation -moz-animation-delay -moz-animation-direction -moz-animation-duration -moz-animation-fill-mode -moz-animation-iteration-count -moz-animation-name -moz-animation-play-state -moz-animation-timing-function -moz-appearance -moz-background-clip -moz-background-inline-policy -moz-background-origin -moz-background-size -moz-binding -moz-border-bottom-colors -moz-border-end -moz-border-end-color -moz-border-end-style -moz-border-end-width -moz-border-image -moz-border-left-colors -moz-border-radius -moz-border-radius-bottomleft -moz-border-radius-bottomright -moz-border-radius-topleft -moz-border-radius-topright -moz-border-right-colors -moz-border-start -moz-border-start-color -moz-border-start-style -moz-border-start-width -moz-border-top-colors -moz-box-align -moz-box-direction -moz-box-flex -moz-box-flex-group -moz-box-flexgroup -moz-box-ordinal-group -moz-box-orient -moz-box-pack -moz-box-shadow -moz-box-sizing -moz-column-count -moz-column-gap -moz-column-rule -moz-column-rule-color -moz-column-rule-style -moz-column-rule-width -moz-column-width -moz-context-properties -moz-float-edge -moz-force-broken-image-icon -moz-image-region -moz-linear-gradient -moz-margin-end -moz-margin-start -moz-opacity -moz-outline -moz-outline-color -moz-outline-offset -moz-outline-radius -moz-outline-radius-bottomleft -moz-outline-radius-bottomright -moz-outline-radius-topleft -moz-outline-radius-topright -moz-outline-style -moz-outline-width -moz-padding-end -moz-padding-start -moz-radial-gradient -moz-stack-sizing -moz-text-decoration-color -moz-text-decoration-line -moz-text-decoration-style -moz-transform -moz-transform-origin -moz-transition -moz-transition-delay -moz-transition-duration -moz-transition-property -moz-transition-timing-function -moz-user-focus -moz-user-input -moz-user-modify -moz-user-select -moz-window-shadow -ms-filter -ms-transform -ms-transform-origin -o-transform -webkit-animation -webkit-animation-delay -webkit-animation-direction -webkit-animation-duration -webkit-animation-fill-mode -webkit-animation-iteration-count -webkit-animation-name -webkit-animation-play-state -webkit-animation-timing-function -webkit-appearance -webkit-backface-visibility -webkit-background-clip -webkit-background-composite -webkit-background-origin -webkit-background-size -webkit-border-bottom-left-radius -webkit-border-bottom-right-radius -webkit-border-horizontal-spacing -webkit-border-image -webkit-border-radius -webkit-border-top-left-radius -webkit-border-top-right-radius -webkit-border-vertical-spacing -webkit-box-align -webkit-box-direction -webkit-box-flex -webkit-box-flex-group -webkit-box-lines -webkit-box-ordinal-group -webkit-box-orient -webkit-box-pack -webkit-box-reflect -webkit-box-shadow -webkit-box-sizing -webkit-column-break-after -webkit-column-break-before -webkit-column-break-inside -webkit-column-count -webkit-column-gap -webkit-column-rule -webkit-column-rule-color -webkit-column-rule-style -webkit-column-rule-width -webkit-column-width -webkit-columns -webkit-dashboard-region -webkit-font-smoothing -webkit-gradient -webkit-line-break -webkit-linear-gradient -webkit-margin-bottom-collapse -webkit-margin-collapse -webkit-margin-start -webkit-margin-top-collapse -webkit-marquee -webkit-marquee-direction -webkit-marquee-increment -webkit-marquee-repetition -webkit-marquee-speed -webkit-marquee-style -webkit-mask -webkit-mask-attachment -webkit-mask-box-image -webkit-mask-clip -webkit-mask-composite -webkit-mask-image -webkit-mask-origin -webkit-mask-position -webkit-mask-position-x -webkit-mask-position-y -webkit-mask-repeat -webkit-mask-size -webkit-nbsp-mode -webkit-padding-start -webkit-perspective -webkit-perspective-origin -webkit-radial-gradient -webkit-rtl-ordering -webkit-tap-highlight-color -webkit-text-fill-color -webkit-text-security -webkit-text-size-adjust -webkit-text-stroke -webkit-text-stroke-color -webkit-text-stroke-width -webkit-touch-callout -webkit-transform -webkit-transform-origin -webkit-transform-origin-x -webkit-transform-origin-y -webkit-transform-origin-z -webkit-transform-style -webkit-transition -webkit-transition-delay -webkit-transition-duration -webkit-transition-property -webkit-transition-timing-function -webkit-user-drag -webkit-user-modify -webkit-user-select align-content align-items align-self alignment-adjust alignment-baseline all animation animation-delay animation-direction animation-duration animation-fill-mode animation-iteration-count animation-name animation-play-state animation-timing-function appearance azimuth backface-visibility background background-attachment background-blend-mode background-break background-clip background-color background-image background-origin background-position background-position-x background-position-y background-repeat background-size baseline-shift binding bleed block-size bookmark-label bookmark-level bookmark-state bookmark-target border border-block border-block-end border-block-start border-bottom border-bottom-color border-bottom-left-radius border-bottom-right-radius border-bottom-style border-bottom-width border-collapse border-color border-image border-image-outset border-image-repeat border-image-slice border-image-source border-image-width border-inline border-inline-end border-inline-end-width border-inline-start border-inline-start-color border-inline-start-style border-inline-start-width border-left border-left-color border-left-style border-left-width border-radius border-right border-right-color border-right-style border-right-width border-spacing border-style border-top border-top-color border-top-left-radius border-top-right-radius border-top-style border-top-width border-width bottom box-align box-decoration-break box-direction box-flex box-flex-group box-lines box-ordinal-group box-orient box-pack box-shadow box-sizing break-after break-before break-inside caption-side caret-color clear clip color color-profile column-count column-fill column-gap column-rule column-rule-color column-rule-style column-rule-width column-span column-width columns content counter-increment counter-reset crop cue cue-after cue-before cursor direction display dominant-baseline drop-initial-after-adjust drop-initial-after-align drop-initial-before-adjust drop-initial-before-align drop-initial-size drop-initial-value elevation empty-cells fill fill-opacity filter fit fit-position flex flex-basis flex-direction flex-flow flex-grow flex-shrink flex-wrap float float-offset font font-effect font-emphasize font-family font-size font-size-adjust font-stretch font-style font-variant font-variant-ligatures font-weight gap grid-area grid-auto-flow grid-auto-rows grid-column grid-column-end grid-column-gap grid-column-start grid-columns grid-gap grid-row grid-row-gap grid-rows grid-template-areas grid-template-columns grid-template-rows hanging-punctuation height hyphenate-after hyphenate-before hyphenate-character hyphenate-lines hyphenate-resource hyphens icon image-orientation image-rendering image-resolution inline-box-align inline-size inset inset-inline-end inset-inline-start justify-content justify-items justify-self left letter-spacing line-height line-stacking line-stacking-ruby line-stacking-shift line-stacking-strategy list-style list-style-image list-style-position list-style-type margin margin-block margin-block-end margin-block-start margin-bottom margin-inline margin-inline-end margin-inline-start margin-left margin-right margin-top mark mark-after mark-before marker-offset marks marquee-direction marquee-play-count marquee-speed marquee-style mask mask-clip mask-image mask-origin mask-position mask-position-x mask-repeat mask-size max-height max-width min-block-size min-height min-inline-size min-width mix-blend-mode move-to nav-down nav-index nav-left nav-right nav-up object-fit opacity order orphans outline outline-color outline-offset outline-style outline-width overflow overflow-anchor overflow-style overflow-wrap overflow-x overflow-y padding padding-block padding-block-end padding-block-start padding-bottom padding-inline padding-inline-end padding-inline-start padding-left padding-right padding-top page page-break-after page-break-before page-break-inside page-policy paint-order pause pause-after pause-before perspective perspective-origin phonemes pitch pitch-range play-during pointer-events position presentation-level punctuation-trim quotes rendering-intent resize rest rest-after rest-before richness right rotation rotation-point ruby-align ruby-overhang ruby-position ruby-span scrollbar-color size speak speak-header speak-numeral speak-punctuation speech-rate stress string-set stroke stroke-dasharray stroke-linejoin stroke-opacity stroke-width tab-size table-layout target target-name target-new target-position text-align text-align-last text-anchor text-decoration text-decoration-color text-decoration-line text-decoration-style text-emphasis text-height text-indent text-justify text-outline text-overflow text-rendering text-shadow text-transform text-wrap top transform transform-origin transform-style transition transition-delay transition-duration transition-property transition-timing-function unicode-bidi user-select vector-effect vertical-align visibility voice-balance voice-duration voice-family voice-pitch voice-pitch-range voice-rate voice-stress voice-volume volume white-space white-space-collapse widows width will-change word-break word-spacing word-wrap z-index", + [1] = "active after before check checked disabled empty enabled first first-child first-letter first-line first-of-type focus hover indeterminate invalid lang last-child last-of-type left link not nth-child nth-last-child nth-of-type nth-last-of-type only-child only-of-type optional read-only read-write required right root selection target valid visited", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["TAG"] = { + id = 1, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["CLASS"] = { + id = 2, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["PSEUDOCLASS"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["UNKNOWN_PSEUDOCLASS"] = { + id = 4, + fgColor = rgb(0xFF8080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 6, + fgColor = rgb(0x8080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["UNKNOWN_IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["VALUE"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 9, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["ID"] = { + id = 10, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IMPORTANT"] = { + id = 11, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DIRECTIVE"] = { + id = 12, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/d.lua b/src/NotepadNext/languages/d.lua new file mode 100644 index 000000000..301de4707 --- /dev/null +++ b/src/NotepadNext/languages/d.lua @@ -0,0 +1,131 @@ +local L = {} + +L.lexer = "d" + +L.singleLineComment = "// " + +L.extensions = { + "d", +} + +L.keywords = { + [0] = "abstract alias align asm assert auto body bool break byte case cast catch cdouble cent cfloat char class const continue creal dchar debug default delegate delete deprecated do double else enum export extern false final finally float for foreach foreach_reverse function goto idouble if ifloat immutable import in inout int interface invariant ireal is lazy long mixin module new nothrow null out override package pragma private protected public pure real ref return scope shared short static struct super switch synchronized template this throw true try typedef typeid typeof ubyte ucent uint ulong union unittest ushort version void volatile wchar while with", + [1] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 6, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEWORD1"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEWORD2"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEWORD3"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEWORD4"] = { + id = 20, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEWORD5"] = { + id = 21, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEWORD6"] = { + id = 22, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 5, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 10, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 12, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 13, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT NESTED"] = { + id = 4, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 16, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["STRING B"] = { + id = 18, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING R"] = { + id = 19, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/diff.lua b/src/NotepadNext/languages/diff.lua new file mode 100644 index 000000000..453bec4bb --- /dev/null +++ b/src/NotepadNext/languages/diff.lua @@ -0,0 +1,51 @@ +local L = {} + +L.lexer = "diff" + +L.extensions = { + "diff", + "patch", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMAND"] = { + id = 2, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["HEADER"] = { + id = 3, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["POSITION"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["DELETED"] = { + id = 5, + fgColor = rgb(0x808040), + bgColor = rgb(defaultBg), + }, + ["ADDED"] = { + id = 6, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/erlang.lua b/src/NotepadNext/languages/erlang.lua new file mode 100644 index 000000000..75d7f8f2e --- /dev/null +++ b/src/NotepadNext/languages/erlang.lua @@ -0,0 +1,159 @@ +local L = {} + +L.lexer = "erlang" + +L.singleLineComment = "% " + +L.extensions = { + "erl", + "hrl", +} + +L.keywords = { + [0] = "after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor", + [1] = "erlang: abs adler32 adler32_combine erlang:append_element apply atom_to_binary atom_to_list binary_to_atom binary_to_existing_atom binary_to_list bitstring_to_list binary_to_term bit_size erlang:bump_reductions byte_size erlang:cancel_timer check_process_code concat_binary crc32 crc32_combine date decode_packet delete_module erlang:demonitor disconnect_node erlang:display element erase erlang:error exit float float_to_list erlang:fun_info erlang:fun_to_list erlang:function_exported garbage_collect get erlang:get_cookie get_keys erlang:get_stacktrace group_leader halt erlang:hash hd erlang:hibernate integer_to_list erlang:integer_to_list iolist_to_binary iolist_size is_alive is_atom is_binary is_bitstring is_boolean erlang:is_builtin is_float is_function is_integer is_list is_number is_pid is_port is_process_alive is_record is_reference is_tuple length link list_to_atom list_to_binary list_to_bitstring list_to_existing_atom list_to_float list_to_integer erlang:list_to_integer list_to_pid list_to_tuple load_module erlang:load_nif erlang:loaded erlang:localtime erlang:localtime_to_universaltime make_ref erlang:make_tuple erlang:max erlang:md5 erlang:md5_final erlang:md5_init erlang:md5_update erlang:memory erlang:min module_loaded erlang:monitor monitor_node node nodes now open_port erlang:phash erlang:phash2 pid_to_list port_close port_command erlang:port_command port_connect port_control erlang:port_call erlang:port_info erlang:port_to_list erlang:ports pre_loaded erlang:process_display process_flag process_info processes purge_module put erlang:raise erlang:read_timer erlang:ref_to_list register registered erlang:resume_process round self erlang:send erlang:send_after erlang:send_nosuspend erlang:set_cookie setelement size spawn spawn_link spawn_monitor spawn_opt split_binary erlang:start_timer statistics erlang:suspend_process erlang:system_flag erlang:system_info erlang:system_monitor erlang:system_profile term_to_binary throw time tl erlang:trace erlang:trace_delivered erlang:trace_info erlang:trace_pattern trunc tuple_size tuple_to_list erlang:universaltime erlang:universaltime_to_localtime unlink unregister whereis erlang:yield", + [2] = "-define -else -endif -ifdef -ifndef -include -include_lib -undef", + [3] = "-behavior -behaviour -compile -created -created_by -export -file -import -module -modified -modified_by -record -revision -spec -type -vsn", + [4] = "@author @clear @copyright @deprecated @doc @docfile @end @equiv @headerfile @hidden @private @reference @see @since @spec @throws @title @todo @TODO @type @version", + [5] = "@date @docRoot @link @module @package @section @time @type @version", +} + +L.styles = { + ["DEFAULT STYLE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DEFAULT COMMENT"] = { + id = 1, + fgColor = rgb(0xd00000), + bgColor = rgb(defaultBg), + }, + ["FUNCTION COMMENT"] = { + id = 14, + fgColor = rgb(0x3f5fbf), + bgColor = rgb(defaultBg), + }, + ["MODULE COMMENT"] = { + id = 15, + fgColor = rgb(0x3f5fbf), + bgColor = rgb(defaultBg), + }, + ["DOCUMENTATION HELPER IN COMMENT"] = { + id = 16, + fgColor = rgb(0x3f5fbf), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DOCUMENTATION MACRO IN COMMENT"] = { + id = 17, + fgColor = rgb(0x3f5fbf), + bgColor = rgb(defaultBg), + fontStyle = 3, + }, + ["VARIABLE"] = { + id = 2, + fgColor = rgb(0x7f0000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0x007f00), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 5, + fgColor = rgb(0xff901e), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 9, + fgColor = rgb(0x007f00), + bgColor = rgb(defaultBg), + }, + ["MACRO"] = { + id = 10, + fgColor = rgb(0x7f007f), + bgColor = rgb(defaultBg), + }, + ["MACRO QUOTED"] = { + id = 19, + fgColor = rgb(0x7f007f), + bgColor = rgb(defaultBg), + }, + ["RECORD"] = { + id = 11, + fgColor = rgb(0x7f7f00), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["RECORD QUOTED"] = { + id = 20, + fgColor = rgb(0x7f7f00), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["ATOM"] = { + id = 7, + fgColor = rgb(0x7f7f00), + bgColor = rgb(defaultBg), + }, + ["ATOM QUOTED"] = { + id = 18, + fgColor = rgb(0x7f7f00), + bgColor = rgb(defaultBg), + }, + ["NODE NAME"] = { + id = 13, + fgColor = rgb(0x007f7f), + bgColor = rgb(defaultBg), + }, + ["NODE NAME QUOTED"] = { + id = 21, + fgColor = rgb(0x007f7f), + bgColor = rgb(defaultBg), + }, + ["RESERVED WORDS"] = { + id = 4, + fgColor = rgb(0x00007f), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["BUILT-IN FUNCTIONS"] = { + id = 22, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION NAME"] = { + id = 8, + fgColor = rgb(0x00007f), + bgColor = rgb(defaultBg), + }, + ["MODULE NAME"] = { + id = 23, + fgColor = rgb(0x00cccc), + bgColor = rgb(defaultBg), + }, + ["MODULE ATTRIBUTES"] = { + id = 24, + fgColor = rgb(0x007f7f), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 12, + fgColor = rgb(0x007f7f), + bgColor = rgb(defaultBg), + }, + ["OPERATORS"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["UNKNOWN: ERROR"] = { + id = 31, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFF0000), + }, +} +return L diff --git a/src/NotepadNext/languages/escript.lua b/src/NotepadNext/languages/escript.lua new file mode 100644 index 000000000..38931358c --- /dev/null +++ b/src/NotepadNext/languages/escript.lua @@ -0,0 +1,80 @@ +local L = {} + +L.lexer = "escript" + +L.singleLineComment = "// " + +L.extensions = { + "src", + "em", +} + +L.keywords = { + [0] = "basic basicio boats cfgfile file http npc os uo util accessible addmenuitem appendconfigfileelem applyconstraint applydamage applyrawdamage assignrecttoweatherregion append baseskilltorawskill boatfromitem broadcast ban cdbl cint cstr checklineofsight checklosat checkskill consumemana consumereagents consumesubstance createaccount createitematlocation createiteminbackpack createitemininventory createitemincontainer createmenu createmultiatlocation createnpcfromtemplate createrootiteminstoragearea createstoragearea clear_script_profile_counters close damage destroyitem destroymulti destroyrootiteminstoragearea detach disableevents disconnectclient distance disable enableevents enumerateitemsincontainer enumerateonlinecharacters equipfromtemplate equipitem eraseglobalproperty eraseobjproperty enable enabled erase events_waiting exists findconfigelem findobjtypeincontainer findrootiteminstoragearea findstoragearea fclose find fopen fread fseek ftell fwrite gamestat getamount getcommandhelp getconfigint getconfigintkeys getconfigmaxintkey getconfigreal getconfigstring getconfigstringkeys getconfigstringarray getelemproperty getequipmentbylayer getglobalproperty getharvestdifficulty getmapinfo getmenuobjtypes getobjproperty getobjtype getobjtypebyname getproperty getrawskill getregionstring getskill getspelldifficulty getstandingheight getworldheight grantprivilege harvestresource healdamage hex islegalmove insert keys listequippeditems listghostsnearlocation listhostiles listitemsatlocation listitemsnearlocation listitemsnearlocationoftype listmobilesinlineofsight listmobilesnearlocation listmobilesnearlocationex listobjectsinbox loadtusscpfile left len log_profile lower makeboundingbox move moveboat moveboatrelative movecharactertolocation moveitemtocontainer moveitemtolocation move_offline_mobiles openpaperdoll open pack performaction playlightningbolteffect playmovingeffect playmovingeffectxyz playobjectcenteredeffect playsoundeffect playsoundeffectprivate playstationaryeffect printtextabove printtextaboveprivate packages polcore position print queryparam randomdiceroll randomint rawskilltobaseskill readconfigfile readgameclock releaseitem registerforspeechevents registeritemwithboat requestinput reserveitem restartscript resurrect revokeprivilege runawayfrom runawayfromlocation runtoward runtowardlocation reverse run_script_to_completion saveworldstate selectmenuitem2 self sendbuywindow senddialoggump sendevent sendopenspecialcontainer sendpacket sendsellwindow sendskillwindow sendstringastipwindow sendsysmessage sendtextentrygump setanchor setglobalproperty setname setobjproperty setopponent setproperty setrawskill setregionlightlevel setregionweatherlevel setscriptcontroller setwarmode shutdown speakpowerwords splitwords startspelleffect subtractamount systemfindboatbyserial systemfindobjectbyserial say set_critical set_debug set_priority set_priority_divide set_script_option setcmdlevel setdex setint setlightlevel setmaster setname setpassword setstr shrink size sleep sleepms sort spendgold squelch start_script syslog system_rpm target targetcoordinates targetmultiplacement turnawayfrom turnawayfromlocation turnboat turntoward turntowardlocation toggle unloadconfigfile unpack unban unload_scripts upper walkawayfrom walkawayfromlocation walktoward walktowardlocation wander writehtml writehtmlraw wait_for_event movechar_forcelocation moveitem_forcelocation moveitem_normal scriptopt_debug scriptopt_no_interrupt scriptopt_no_runaway te_cancel_disable te_cancel_enable te_style_disable te_style_normal te_style_numerical tgtopt_check_los tgtopt_harmful tgtopt_helpful tgtopt_neutral tgtopt_nocheck_los setprop getprop", + [1] = "array const dictionary global local var and default in next not or return to include use enum", + [2] = "while for endfor function program endprogram endfunction foreach case else elseif if endcase endenum endforeach endif endwhile", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["LINE COMMENT"] = { + id = 2, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["DOC COMMENT"] = { + id = 3, + fgColor = rgb(0x3F703F), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD"] = { + id = 5, + fgColor = rgb(0xFF4000), + bgColor = rgb(defaultBg), + }, + ["DOUBLE QUOTED STRING"] = { + id = 6, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["OPERATORS"] = { + id = 7, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIERS"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["BRACES"] = { + id = 9, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["KEYWORDS2"] = { + id = 10, + fgColor = rgb(0xB00040), + bgColor = rgb(defaultBg), + }, + ["KEYWORDS3"] = { + id = 11, + fgColor = rgb(0xB00040), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/forth.lua b/src/NotepadNext/languages/forth.lua new file mode 100644 index 000000000..7a0d36668 --- /dev/null +++ b/src/NotepadNext/languages/forth.lua @@ -0,0 +1,88 @@ +local L = {} + +L.lexer = "forth" + +L.singleLineComment = "\\ " + +L.extensions = { + "forth", +} + +L.keywords = { + [0] = "AGAIN BEGIN CASE DO ELSE ENDCASE ENDOF IF LOOP OF REPEAT THEN UNTIL WHILE [IF] [ELSE] [THEN] ?DO", + [1] = "DUP DROP ROT SWAP OVER @ ! 2@ 2! 2DUP 2DROP 2SWAP 2OVER NIP R@ >R R> 2R@ 2>R 2R> 0= 0< SP@ SP! W@ W! C@ C! < > = <> 0<>SPACE SPACES KEY? KEY THROW CATCH ABORT */ 2* /MOD CELL+ CELLS CHAR+ CHARS MOVE ERASE DABS TITLE HEX DECIMAL HOLD <# # #S #> SIGN D. . U. DUMP (.\") >NUMBER ' IMMEDIATE EXIT RECURSE UNLOOP LEAVE HERE ALLOT , C, W, COMPILE, BRANCH, RET, LIT, DLIT, ?BRANCH, \", >MARK >RESOLVE1 RESOLVE ALIGN ALIGNED USER-ALLOT USER-HERE HEADER DOES> SMUDGE HIDE :NONAME LAST-WORD ?ERROR ERROR2 FIND1 SFIND SET-CURRENT GET-CURRENT DEFINITIONS GET-ORDER FORTH ONLY SET-ORDER ALSO PREVIOUS VOC-NAME. ORDER LATEST LITERAL 2LITERAL SLITERAL CLITERAL ?LITERAL1 ?SLITERAL1 HEX-LITERAL HEX-SLITERAL ?LITERAL2 ?SLITERAL2 SOURCE EndOfChunk CharAddr PeekChar IsDelimiter GetChar OnDelimiter SkipDelimiters OnNotDelimiter SkipWord SkipUpTo ParseWord NextWord PARSE SKIP CONSOLE-HANDLES REFILL DEPTH ?STACK ?COMP WORD INTERPRET BYE QUIT MAIN1 EVALUATE INCLUDE-FILE INCLUDED >BODY +WORD WORDLIST CLASS! CLASS@ PAR! PAR@ ID. ?IMMEDIATE ?VOC IMMEDIATE VOC WordByAddrWl WordByAddr NLIST WORDS SAVE OPTIONS /notransl ANSI>OEM ACCEPT EMIT CR TYPE EKEY? EKEY EKEY>CHAR EXTERNTASK ERASE-IMPORTS ModuleName ModuleDirName ENVIRONMENT? DROP-EXC-HANDLER SET-EXC-HANDLER HALT ERR CLOSE-FILE CREATE-FILE CREATE-FILE-SHARED OPEN-FILE-SHARED DELETE-FILE FILE-POSITION FILE-SIZE OPEN-FILE READ-FILE REPOSITION-FILE DOS-LINES UNIX-LINES READ-LINE WRITE-FILE RESIZE-FILE WRITE-LINE ALLOCATE FREE RESIZE START SUSPEND RESUME STOP PAUSE MIN MAX TRUE FALSE ASCIIZ> R/O W/O ;CLASS ENDWITH OR AND /STRING SEARCH COMPARE EXPORT ;MODULE SPACE", + [2] = "VARIABLE CREATE : VALUE CONSTANT VM: M: var dvar chars OBJ CONSTR: DESTR: CLASS: OBJECT: POINTER USER USER-CREATE USER-VALUE VECT WNDPROC: VOCABULARY -- TASK: CEZ: MODULE:", + [3] = "CHAR [CHAR] POSTPONE WITH ['] TO [COMPILE] CHAR ASCII \'", + [4] = "REQUIRE WINAPI", + [5] = "S\" ABORT\" Z\" \" .\" C\"", +} + +L.styles = { + ["WHITESPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x009933), + bgColor = rgb(defaultBg), + }, + ["ML COMMENT"] = { + id = 2, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 3, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["CONTROL"] = { + id = 4, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DEFWORDS"] = { + id = 6, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREWORD1"] = { + id = 7, + fgColor = rgb(0xCC3300), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREWORD2"] = { + id = 8, + fgColor = rgb(0x996633), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 9, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["DOUBLE QUOTED STRING"] = { + id = 10, + fgColor = rgb(0xCC3300), + bgColor = rgb(defaultBg), + }, + ["LOCALE"] = { + id = 11, + fgColor = rgb(0x0000CC), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/fortran.lua b/src/NotepadNext/languages/fortran.lua new file mode 100644 index 000000000..ebc0eebed --- /dev/null +++ b/src/NotepadNext/languages/fortran.lua @@ -0,0 +1,100 @@ +local L = {} + +L.lexer = "fortran" + +L.singleLineComment = "! " + +L.extensions = { + "f", + "for", + "f90", + "f95", + "f2k", + "f23", +} + +L.keywords = { + [0] = "access action advance allocatable allocate apostrophe assign assignment associate asynchronous backspace bind blank blockdata call case character class close common complex contains continue critical cycle data deallocate decimal delim default dimension direct do dowhile double doubleprecision else elseif elsewhere encoding end endassociate endblockdata endcritical enddo endenum endfile endforall endfunction endif endinterface endmodule endprocedure endprogram endselect endsubmodule endsubroutine endtype endwhere entry enum eor equivalence err errmsg exist exit external file flush fmt forall form format formatted function go goto id if implicit in include inout integer inquire intent interface intrinsic iomsg iolength iostat kind len logical module name named namelist nextrec nml none nullify number only open opened operator optional out pad parameter pass pause pending pointer pos position precision print private procedure program protected public quote read readwrite real rec recl recursive result return rewind save select selectcase selecttype sequential sign size stat status stop stream submodule subroutine target then to type unformatted unit use value volatile wait where while write", + [1] = "abs achar acos acosd adjustl adjustr aimag aimax0 aimin0 aint ajmax0 ajmin0 akmax0 akmin0 all allocated alog alog10 amax0 amax1 amin0 amin1 amod anint any asin asind associated atan atan2 atan2d atand bitest bitl bitlr bitrl bjtest bit_size bktest break btest cabs ccos cdabs cdcos cdexp cdlog cdsin cdsqrt ceiling cexp char clog cmplx conjg cos cosd cosh count cpu_time cshift csin csqrt dabs dacos dacosd dasin dasind datan datan2 datan2d datand date date_and_time dble dcmplx dconjg dcos dcosd dcosh dcotan ddim dexp dfloat dflotk dfloti dflotj digits dim dimag dint dlog dlog10 dmax1 dmin1 dmod dnint dot_product dprod dreal dsign dsin dsind dsinh dsqrt dtan dtand dtanh eoshift epsilon errsns exp exponent float floati floatj floatk floor fraction free huge iabs iachar iand ibclr ibits ibset ichar idate idim idint idnint ieor ifix iiabs iiand iibclr iibits iibset iidim iidint iidnnt iieor iifix iint iior iiqint iiqnnt iishft iishftc iisign ilen imax0 imax1 imin0 imin1 imod index inint inot int int1 int2 int4 int8 iqint iqnint ior ishft ishftc isign isnan izext jiand jibclr jibits jibset jidim jidint jidnnt jieor jifix jint jior jiqint jiqnnt jishft jishftc jisign jmax0 jmax1 jmin0 jmin1 jmod jnint jnot jzext kiabs kiand kibclr kibits kibset kidim kidint kidnnt kieor kifix kind kint kior kishft kishftc kisign kmax0 kmax1 kmin0 kmin1 kmod knint knot kzext lbound leadz len len_trim lenlge lge lgt lle llt log log10 logical lshift malloc matmul max max0 max1 maxexponent maxloc maxval merge min min0 min1 minexponent minloc minval mod modulo mvbits nearest nint not nworkers number_of_processors pack popcnt poppar precision present product radix random random_number random_seed range real repeat reshape rrspacing rshift scale scan secnds selected_int_kind selected_real_kind set_exponent shape sign sin sind sinh size sizeof sngl snglq spacing spread sqrt sum system_clock tan tand tanh tiny transfer transpose trim ubound unpack verify", + [2] = "cdabs cdcos cdexp cdlog cdsin cdsqrt cotan cotand dcmplx dconjg dcotan dcotand decode dimag dll_export dll_import doublecomplex dreal dvchk encode find flen flush getarg getcharqq getcl getdat getenv gettim hfix ibchng identifier imag int1 int2 int4 intc intrup invalop iostat_msg isha ishc ishl jfix lacfar locking locnear map nargs nbreak ndperr ndpexc offset ovefl peekcharqq precfill prompt qabs qacos qacosd qasin qasind qatan qatand qatan2 qcmplx qconjg qcos qcosd qcosh qdim qexp qext qextd qfloat qimag qlog qlog10 qmax1 qmin1 qmod qreal qsign qsin qsind qsinh qsqrt qtan qtand qtanh ran rand randu rewrite segment setdat settim system timer undfl unlock union val virtual volatile zabs zcos zexp zlog zsin zsqrt", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING2"] = { + id = 4, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 8, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION1"] = { + id = 9, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION2"] = { + id = 10, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREPROCESSOR"] = { + id = 11, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["OPERATOR2"] = { + id = 12, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 13, + fgColor = rgb(defaultBg), + bgColor = rgb(0xFF80FF), + fontStyle = 1, + }, + ["CONTINUATION"] = { + id = 14, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/fortran77.lua b/src/NotepadNext/languages/fortran77.lua new file mode 100644 index 000000000..3d6af3e2e --- /dev/null +++ b/src/NotepadNext/languages/fortran77.lua @@ -0,0 +1,95 @@ +local L = {} + +L.lexer = "fortran77" + +L.singleLineComment = "C " + +L.extensions = { + "f77", +} + +L.keywords = { + [0] = "access action advance allocatable allocate apostrophe assign assignment associate asynchronous backspace bind blank blockdata call case character class close common complex contains continue critical cycle data deallocate decimal delim default dimension direct do dowhile double doubleprecision else elseif elsewhere encoding end endassociate endblockdata endcritical enddo endenum endfile endforall endfunction endif endinterface endmodule endprocedure endprogram endselect endsubmodule endsubroutine endtype endwhere entry enum eor equivalence err errmsg exist exit external file flush fmt forall form format formatted function go goto id if implicit in include inout integer inquire intent interface intrinsic iomsg iolength iostat kind len logical module name named namelist nextrec nml none nullify number only open opened operator optional out pad parameter pass pause pending pointer pos position precision print private procedure program protected public quote read readwrite real rec recl recursive result return rewind save select selectcase selecttype sequential sign size stat status stop stream submodule subroutine target then to type unformatted unit use value volatile wait where while write", + [1] = "abs achar acos acosd adjustl adjustr aimag aimax0 aimin0 aint ajmax0 ajmin0 akmax0 akmin0 all allocated alog alog10 amax0 amax1 amin0 amin1 amod anint any asin asind associated atan atan2 atan2d atand bitest bitl bitlr bitrl bjtest bit_size bktest break btest cabs ccos cdabs cdcos cdexp cdlog cdsin cdsqrt ceiling cexp char clog cmplx conjg cos cosd cosh count cpu_time cshift csin csqrt dabs dacos dacosd dasin dasind datan datan2 datan2d datand date date_and_time dble dcmplx dconjg dcos dcosd dcosh dcotan ddim dexp dfloat dflotk dfloti dflotj digits dim dimag dint dlog dlog10 dmax1 dmin1 dmod dnint dot_product dprod dreal dsign dsin dsind dsinh dsqrt dtan dtand dtanh eoshift epsilon errsns exp exponent float floati floatj floatk floor fraction free huge iabs iachar iand ibclr ibits ibset ichar idate idim idint idnint ieor ifix iiabs iiand iibclr iibits iibset iidim iidint iidnnt iieor iifix iint iior iiqint iiqnnt iishft iishftc iisign ilen imax0 imax1 imin0 imin1 imod index inint inot int int1 int2 int4 int8 iqint iqnint ior ishft ishftc isign isnan izext jiand jibclr jibits jibset jidim jidint jidnnt jieor jifix jint jior jiqint jiqnnt jishft jishftc jisign jmax0 jmax1 jmin0 jmin1 jmod jnint jnot jzext kiabs kiand kibclr kibits kibset kidim kidint kidnnt kieor kifix kind kint kior kishft kishftc kisign kmax0 kmax1 kmin0 kmin1 kmod knint knot kzext lbound leadz len len_trim lenlge lge lgt lle llt log log10 logical lshift malloc matmul max max0 max1 maxexponent maxloc maxval merge min min0 min1 minexponent minloc minval mod modulo mvbits nearest nint not nworkers number_of_processors pack popcnt poppar precision present product radix random random_number random_seed range real repeat reshape rrspacing rshift scale scan secnds selected_int_kind selected_real_kind set_exponent shape sign sin sind sinh size sizeof sngl snglq spacing spread sqrt sum system_clock tan tand tanh tiny transfer transpose trim ubound unpack verify", + [2] = "cdabs cdcos cdexp cdlog cdsin cdsqrt cotan cotand dcmplx dconjg dcotan dcotand decode dimag dll_export dll_import doublecomplex dreal dvchk encode find flen flush getarg getcharqq getcl getdat getenv gettim hfix ibchng identifier imag int1 int2 int4 intc intrup invalop iostat_msg isha ishc ishl jfix lacfar locking locnear map nargs nbreak ndperr ndpexc offset ovefl peekcharqq precfill prompt qabs qacos qacosd qasin qasind qatan qatand qatan2 qcmplx qconjg qcos qcosd qcosh qdim qexp qext qextd qfloat qimag qlog qlog10 qmax1 qmin1 qmod qreal qsign qsin qsind qsinh qsqrt qtan qtand qtanh ran rand randu rewrite segment setdat settim system timer undfl unlock union val virtual volatile zabs zcos zexp zlog zsin zsqrt", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING2"] = { + id = 4, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 8, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION1"] = { + id = 9, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION2"] = { + id = 10, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREPROCESSOR"] = { + id = 11, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["OPERATOR2"] = { + id = 12, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 13, + fgColor = rgb(defaultBg), + bgColor = rgb(0xFF80FF), + fontStyle = 1, + }, + ["CONTINUATION"] = { + id = 14, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/freebasic.lua b/src/NotepadNext/languages/freebasic.lua new file mode 100644 index 000000000..d00f5e7dd --- /dev/null +++ b/src/NotepadNext/languages/freebasic.lua @@ -0,0 +1,97 @@ +local L = {} + +L.lexer = "freebasic" + +L.singleLineComment = "' " + +L.extensions = { + "bas", + "bi", +} + +L.keywords = { + [0] = "append as asc asin asm atan2 atn beep bin binary bit bitreset bitset bload bsave byref byte byval call callocate case cbyte cdbl cdecl chain chdir chr cint circle clear clng clngint close cls color command common cons const continue cos cshort csign csng csrlin cubyte cuint culngint cunsg curdir cushort custom cvd cvi cvl cvlongint cvs cvshort data date deallocate declare defbyte defdbl defined defint deflng deflngint defshort defsng defstr defubyte defuint defulngint defushort dim dir do double draw dylibload dylibsymbol else elseif end enum environ environ$ eof eqv erase err error exec exepath exit exp export extern field fix flip for fre freefile function get getjoystick getkey getmouse gosub goto hex hibyte hiword if iif imagecreate imagedestroy imp inkey inp input instr int integer is kill lbound lcase left len let lib line lobyte loc local locate lock lof log long longint loop loword lset ltrim mid mkd mkdir mki mkl mklongint mks mkshort mod multikey mutexcreate mutexdestroy mutexlock mutexunlock name next not oct on once open option or out output overload paint palette pascal pcopy peek peeki peeks pipe pmap point pointer poke pokei pokes pos preserve preset print private procptr pset ptr public put random randomize read reallocate redim rem reset restore resume resume next return rgb rgba right rmdir rnd rset rtrim run sadd screen screencopy screeninfo screenlock screenptr screenres screenset screensync screenunlock seek statement seek function selectcase setdate setenviron setmouse settime sgn shared shell shl short shr sin single sizeof sleep space spc sqr static stdcall step stop str string string strptr sub swap system tab tan then threadcreate threadwait time time timer to trans trim type ubound ubyte ucase uinteger ulongint union unlock unsigned until ushort using va_arg va_first va_next val val64 valint varptr view viewprint wait wend while width window windowtitle with write xor zstring", + [1] = "#define #dynamic #else #endif #error #if #ifdef #ifndef #inclib #include #print #static #undef", + [2] = "None", + [3] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD1"] = { + id = 3, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING"] = { + id = 4, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 5, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEYWORD2"] = { + id = 10, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD3"] = { + id = 11, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD4"] = { + id = 12, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 15, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["ERROR"] = { + id = 16, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["HEXNUMBER"] = { + id = 17, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["BINNUMBER"] = { + id = 18, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/go.lua b/src/NotepadNext/languages/go.lua new file mode 100644 index 000000000..9f4499121 --- /dev/null +++ b/src/NotepadNext/languages/go.lua @@ -0,0 +1,129 @@ +local L = {} + +L.lexer = "cpp" + +L.singleLineComment = "// " + +L.extensions = { + "go", +} + +L.properties = { + ["fold.cpp.comment.explicit"] = "0", + ["lexer.cpp.track.preprocessor"] = "0", + ["lexer.cpp.escape.sequence"] = "1", +} + +L.keywords = { + [0] = "bool byte break case chan complex64 complex128 const continue defer default else for func go goto fallthrough false float32 float64 if import int interface int8 int16 int32 int64 len map nil package range return select string struct switch true type uint uintptr uint8 uint16 uint32 uint64 var", + [5] = "FIXME TODO XXX HACK NOTE", +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT"] = { + id = 23, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT DOC"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["TASK MARKER"] = { + id = 26, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/gui4cli.lua b/src/NotepadNext/languages/gui4cli.lua new file mode 100644 index 000000000..591aab219 --- /dev/null +++ b/src/NotepadNext/languages/gui4cli.lua @@ -0,0 +1,70 @@ +local L = {} + +L.lexer = "gui4cli" + +L.singleLineComment = "// " + +L.keywords = { + [0] = "None", + [1] = "None", + [2] = "None", + [3] = "None", + [4] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["GLOBAL"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["EVENT"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["ATTRIBUTE"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["CONTROL"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["COMMAND"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/haskell.lua b/src/NotepadNext/languages/haskell.lua new file mode 100644 index 000000000..802643b15 --- /dev/null +++ b/src/NotepadNext/languages/haskell.lua @@ -0,0 +1,106 @@ +local L = {} + +L.lexer = "haskell" + +L.singleLineComment = "-- " + +L.extensions = { + "hs", + "lhs", + "las", +} + +L.keywords = { + [0] = "as case class data default deriving do else hiding if import in infix infixl infixr instance let module newtype of proc qualified rec then type where _", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 1, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEYWORD"] = { + id = 2, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0x800080), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 4, + fgColor = rgb(0xCA6500), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 5, + fgColor = rgb(0xCA6500), + bgColor = rgb(defaultBg), + }, + ["CLASS"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MODULE"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CAPITAL"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DATA"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IMPORT"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 11, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + }, + ["INSTANCE"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENTLINE"] = { + id = 13, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENTBLOCK"] = { + id = 14, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENTBLOCK2"] = { + id = 15, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENTBLOCK3"] = { + id = 16, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/html.lua b/src/NotepadNext/languages/html.lua new file mode 100644 index 000000000..0035a4a9f --- /dev/null +++ b/src/NotepadNext/languages/html.lua @@ -0,0 +1,125 @@ +local L = {} + +L.lexer = "hypertext" + +L.extensions = { + "html", + "htm", + "shtml", + "shtm", + "xhtml", + "xht", + "hta", + "vue", +} + +L.properties = { + ["fold.html"] = "1", +} + +L.keywords = { + [0] = "^data- a abbr accept accept-charset accesskey acronym action address align alink alt applet archive area article aside async audio autocomplete autofocus axis b background base basefont bdi bdo bgcolor bgsound big blink blockquote body border br button canvas caption cellpadding cellspacing center char charoff charset checkbox checked cite class classid clear code codebase codetype col colgroup color cols colspan command compact content contenteditable contextmenu coords data datafld dataformatas datalist datapagesize datasrc datetime dd declare defer del details dfn dialog dir disabled div dl draggable dropzone dt element em embed enctype event face fieldset figcaption figure file font footer for form formaction formenctype formmethod formnovalidate formtarget frame frameborder frameset h1 h2 h3 h4 h5 h6 head header headers height hgroup hidden hr href hreflang hspace html http-equiv i id iframe image img input ins isindex ismap kbd keygen label lang language leftmargin legend li link list listing longdesc main manifest map marginheight marginwidth mark marquee max maxlength media menu menuitem meta meter method min multicol multiple name nav nobr noembed noframes nohref noresize noscript noshade novalidate nowrap object ol onabort onafterprint onautocomplete onautocompleteerror onbeforeonload onbeforeprint onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus onhashchange oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmessage onmousedown onmouseenter onmouseleave onmousemove onmouseout onmouseover onmouseup onmousewheel onoffline ononline onpagehide onpageshow onpause onplay onplaying onpointercancel onpointerdown onpointerenter onpointerleave onpointerlockchange onpointerlockerror onpointermove onpointerout onpointerover onpointerup onpopstate onprogress onratechange onreadystatechange onredo onreset onresize onscroll onseeked onseeking onselect onshow onsort onstalled onstorage onsubmit onsuspend ontimeupdate ontoggle onundo onunload onvolumechange onwaiting optgroup option output p param password pattern picture placeholder plaintext pre profile progress prompt public q radio readonly rel required reset rev reversed role rows rowspan rp rt rtc ruby rules s samp sandbox scheme scope scoped script seamless section select selected shadow shape size sizes small source spacer span spellcheck src srcdoc standby start step strike strong style sub submit summary sup svg svg:svg tabindex table target tbody td template text textarea tfoot th thead time title topmargin tr track tt type u ul usemap valign value valuetype var version video vlink vspace wbr width xml xmlns xmp", + [5] = "ELEMENT DOCTYPE ATTLIST ENTITY NOTATION", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg) + }, + ["COMMENT"] = { + id = 9, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 5, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["DOUBLESTRING"] = { + id = 6, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SINGLESTRING"] = { + id = 7, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TAG"] = { + id = 1, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["TAGEND"] = { + id = 11, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["TAGUNKNOWN"] = { + id = 2, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["ATTRIBUTE"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["ATTRIBUTEUNKNOWN"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CDATA"] = { + id = 17, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["VALUE"] = { + id = 19, + fgColor = rgb(0xFF8000), + bgColor = rgb(0xFEFDE0), + }, + ["ENTITY"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFEFDE0), + fontStyle = 2, + }, + ["SGML_DEFAULT"] = { + id = 21, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SGML_COMMAND"] = { + id = 22, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SGML_PARAM"] = { + id = 23, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SGML_DOUBLESTRING"] = { + id = 24, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SGML_COMMENT"] = { + id = 29, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/ihex.lua b/src/NotepadNext/languages/ihex.lua new file mode 100644 index 000000000..e2c84c2c0 --- /dev/null +++ b/src/NotepadNext/languages/ihex.lua @@ -0,0 +1,109 @@ +local L = {} + +L.lexer = "ihex" + +L.extensions = { + "hex", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["RECSTART"] = { + id = 1, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["RECTYPE"] = { + id = 2, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["RECTYPE_UNKNOWN"] = { + id = 3, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["BYTECOUNT"] = { + id = 4, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["BYTECOUNT_WRONG"] = { + id = 5, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["NOADDRESS"] = { + id = 6, + fgColor = rgb(0x7F00FF), + bgColor = rgb(defaultBg), + }, + ["DATAADDRESS"] = { + id = 7, + fgColor = rgb(0x007FFF), + bgColor = rgb(defaultBg), + }, + ["STARTADDRESS"] = { + id = 9, + fgColor = rgb(0x007FFF), + bgColor = rgb(defaultBg), + }, + ["ADDRESSFIELD_UNKNOWN"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["EXTENDEDADDRESS"] = { + id = 11, + fgColor = rgb(0x007FFF), + bgColor = rgb(defaultBg), + }, + ["DATA_ODD"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DATA_EVEN"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DATA_UNKNOWN"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["DATA_EMPTY"] = { + id = 15, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CHECKSUM"] = { + id = 16, + fgColor = rgb(0x00BF00), + bgColor = rgb(defaultBg), + }, + ["CHECKSUM_WRONG"] = { + id = 17, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["GARBAGE"] = { + id = 18, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, +} +return L diff --git a/src/NotepadNext/languages/ini.lua b/src/NotepadNext/languages/ini.lua new file mode 100644 index 000000000..dc072bc5c --- /dev/null +++ b/src/NotepadNext/languages/ini.lua @@ -0,0 +1,56 @@ +local L = {} + +L.lexer = "props" + +L.singleLineComment = "; " + +L.first_line = { + "^%[.+%][\r\n]", +} + +L.extensions = { + "ini", + "inf", + "url", + "wer", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["SECTION"] = { + id = 2, + fgColor = rgb(TypeColor), + bgColor = rgb(0xF2F4FF), + fontStyle = 9, + }, + ["ASSIGNMENT"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DEFVAL"] = { + id = 4, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["KEY"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, +} +return L diff --git a/src/NotepadNext/languages/inno.lua b/src/NotepadNext/languages/inno.lua new file mode 100644 index 000000000..4904e53fa --- /dev/null +++ b/src/NotepadNext/languages/inno.lua @@ -0,0 +1,94 @@ +local L = {} + +L.lexer = "inno" + +L.singleLineComment = "; " + +L.extensions = { + "iss", +} + +L.keywords = { + [0] = "code components custommessages dirs files icons ini installdelete langoptions languages messages registry run setup types tasks uninstalldelete uninstallrun _istool", + [1] = "allowcancelduringinstall allownoicons allowrootdirectory allowuncpath alwaysrestart alwaysshowcomponentslist alwaysshowdironreadypage alwaysshowgrouponreadypage alwaysusepersonalgroup appcomments appcontact appcopyright appenddefaultdirname appenddefaultgroupname appid appmodifypath appmutex appname apppublisher apppublisherurl appreadmefile appsupporturl appupdatesurl appvername appversion architecturesallowed architecturesinstallin64bitmode backcolor backcolor2 backcolordirection backsolid changesassociations changesenvironment compression copyrightfontname copyrightfontsize createappdir createuninstallregkey defaultdirname defaultgroupname defaultuserinfoname defaultuserinfoorg defaultuserinfoserial dialogfontname dialogfontsize direxistswarning disabledirpage disablefinishedpage disableprogramgrouppage disablereadymemo disablereadypage disablestartupprompt diskclustersize diskslicesize diskspanning enablesdirdoesntexistwarning encryption extradiskspacerequired flatcomponentslist infoafterfile infobeforefile internalcompresslevel languagedetectionmethod languagecodepage languageid languagename licensefile lzmanumfastbytes mergeduplicatefiles minversion onlybelowversion outputbasefilename outputdir outputmanifestfile password privilegesrequired reservebytes restartifneededbyrun setupiconfile showcomponentsizes showlanguagedialog showtaskstreelines slicesperdisk solidcompression sourcedir timestamprounding timestampsinutc titlefontname titlefontsize touchdate touchtime uninstallable uninstalldisplayicon uninstalldisplayname uninstallfilesdir uninstalllogmode uninstallrestartcomputer updateuninstalllogappname usepreviousappdir usepreviousgroup useprevioussetuptype useprevioustasks useprevioususerinfo userinfopage usesetupldr versioninfocompany versioninfocopyright versioninfodescription versioninfotextversion versioninfoversion welcomefontname welcomefontsize windowshowcaption windowstartmaximized windowresizable windowvisible wizardimagebackcolor wizardimagefile wizardimagestretch wizardsmallimagefile", + [2] = "afterinstall attribs beforeinstall check comment components copymode description destdir destname excludes extradiskspacerequired filename flags fontinstall groupdescription hotkey infoafterfile infobeforefile iconfilename iconindex key languages licensefile messagesfile minversion name onlybelowversion parameters permissions root runonceid section source statusmsg string subkey tasks type types valuedata valuename valuetype workingdir", + [3] = "append define dim elif else emit endif endsub error expr file for if ifdef ifexist ifndef ifnexist include insert pragma sub undef", + [4] = "begin break case const continue do downto else end except finally for function if of procedure repeat then to try until uses var while with", + [5] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["KEYWORD"] = { + id = 2, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PARAMETER"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SECTION"] = { + id = 4, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREPROCESSOR"] = { + id = 5, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PREPROCESSOR INLINE"] = { + id = 6, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT PASCAL"] = { + id = 7, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["KEYWORD PASCAL"] = { + id = 8, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD USER"] = { + id = 9, + fgColor = rgb(0x8080FF), + bgColor = rgb(0xFFFFCC), + fontStyle = 1, + }, + ["STRING DOUBLE"] = { + id = 10, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING SINGLE"] = { + id = 11, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/java.lua b/src/NotepadNext/languages/java.lua new file mode 100644 index 000000000..0ad80f820 --- /dev/null +++ b/src/NotepadNext/languages/java.lua @@ -0,0 +1,120 @@ +local L = {} + +L.lexer = "cpp" + +L.singleLineComment = "// " + +L.extensions = { + "java", +} + +L.properties = { + ["fold.cpp.comment.explicit"] = "0", + ["lexer.cpp.track.preprocessor"] = "0", + ["lexer.cpp.escape.sequence"] = "1", +} + +L.keywords = { + [0] = "instanceof assert if else switch case default break goto return for while do continue new throw throws try catch finally this super extends implements import true false null", + [1] = "package transient strictfp void char short int long double float const static volatile byte boolean class interface native private protected public final abstract synchronized enum", + [5] = "FIXME TODO XXX HACK NOTE", +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["TASK MARKER"] = { + id = 26, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/javascript.lua b/src/NotepadNext/languages/javascript.lua new file mode 100644 index 000000000..6dd4daf15 --- /dev/null +++ b/src/NotepadNext/languages/javascript.lua @@ -0,0 +1,124 @@ +local L = {} + +L.lexer = "cpp" + +L.singleLineComment = "// " + +L.extensions = { + "js", + "mjs", + "cjs", + "jsm", + "jsx", + "ts", + "tsx", +} + +L.properties = { + ["lexer.cpp.backquoted.strings"] = "1", +} + +L.keywords = { + [0] = "abstract async await boolean break byte case catch char class const continue debugger default delete do double else enum export extends final finally float for function goto if implements import in instanceof int interface let long native new null of package private protected public return short static super switch synchronized this throw throws transient try typeof var void volatile while with true false prototype yield from as", + [1] = "Array Date eval hasOwnProperty Infinity isFinite isNaN isPrototypeOf Math NaN Number Object prototype String toString undefined valueOf", + [3] = "alert all anchor anchors area assign blur button checkbox clearInterval clearTimeout clientInformation close closed confirm constructor crypto decodeURI decodeURIComponent defaultStatus document element elements embed embeds encodeURI encodeURIComponent escape event fileUpload focus form forms frame innerHeight innerWidth layer layers link location mimeTypes navigate navigator frames frameRate hidden history image images offscreenBuffering onblur onclick onerror onfocus onkeydown onkeypress onkeyup onmouseover onload onmouseup onmousedown onsubmit open opener option outerHeight outerWidth packages pageXOffset pageYOffset parent parseFloat parseInt password pkcs11 plugin prompt propertyIsEnum radio reset screenX screenY scroll secure select self setInterval setTimeout status submit taint text textarea top unescape untaint window", +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["WINDOW INSTRUCTION"] = { + id = 19, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRINGRAW"] = { + id = 20, + fgColor = rgb(OperatorColor), + bgColor = rgb(0xC0C0C0), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/json.lua b/src/NotepadNext/languages/json.lua new file mode 100644 index 000000000..b8a085dab --- /dev/null +++ b/src/NotepadNext/languages/json.lua @@ -0,0 +1,98 @@ +local L = {} + +L.lexer = "json" + +L.first_line = { + "^{[\r\n]", +} + +L.extensions = { + "json", +} + +L.properties = { + ["lexer.json.escape.sequence"] = "1", + ["lexer.json.allow.comments"] = "1", +} + +L.keywords = { + [0] = "false null true", + [1] = "@id @context @type @value @language @container @list @set @reverse @index @base @vocab @graph", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 1, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 2, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["STRINGEOL"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["PROPERTYNAME"] = { + id = 4, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["ESCAPESEQUENCE"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["LINECOMMENT"] = { + id = 6, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["BLOCKCOMMENT"] = { + id = 7, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["URI"] = { + id = 9, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["COMPACTIRI"] = { + id = 10, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD"] = { + id = 11, + fgColor = rgb(0x18AF8A), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["LDKEYWORD"] = { + id = 12, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["ERROR"] = { + id = 13, + fgColor = rgb(0xFFFF80), + bgColor = rgb(0xFF0000), + }, +} +return L diff --git a/src/NotepadNext/languages/kix.lua b/src/NotepadNext/languages/kix.lua new file mode 100644 index 000000000..0336287e9 --- /dev/null +++ b/src/NotepadNext/languages/kix.lua @@ -0,0 +1,69 @@ +local L = {} + +L.lexer = "kix" + +L.extensions = { + "kix", +} + +L.keywords = { + [0] = "? and beep big break call cd cls color cookie1 copy debug del dim display do until exit flushkb for each next function endfunction get gets global go gosub goto if else endif md or password play quit rd redim return run select case endselect set setl setm settime shell sleep small use while loop", + [1] = "abs addkey addprinterconnection addprogramgroup addprogramitem asc ascan at backupeventlog box cdbl chr cint cleareventlog close comparefiletimes createobject cstr dectohex delkey delprinterconnection delprogramgroup delprogramitem deltree delvalue dir enumgroup enumipinfo enumkey enumlocalgroup enumvalue execute exist existkey expandenvironmentvars fix formatnumber freefilehandle getdiskspace getfileattr getfilesize getfiletime getfileversion getobject iif ingroup instr instrrev int isdeclared join kbhit keyexist lcase left len loadhive loadkey logevent logoff ltrim memorysize messagebox open readline readprofilestring readtype readvalue redirectoutput right rnd round rtrim savekey sendkeys sendmessage setascii setconsole setdefaultprinter setfileattr setfocus setoption setsystemstate settitle setwallpaper showprogramgroup shutdown sidtoname split srnd substr trim ubound ucase unloadhive val vartype vartypename writeline writeprofilestring writevalue", + [2] = "address build color comment cpu crlf csd curdir date day domain dos error fullname homedir homedrive homeshr hostname inwin ipaddress0 ipaddress1 ipaddress2 ipaddress3 kix lanroot ldomain ldrive lm logonmode longhomedir lserver maxpwage mdayno mhz monthno month msecs pid primarygroup priv productsuite producttype pwage ras result rserver scriptdir scriptexe scriptname serror sid site startdir syslang ticks time userid userlang wdayno wksta wuserid ydayno year", +} + +L.styles = { + ["DEFAULT"] = { + id = 31, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 2, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING2"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["VAR"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["MACRO"] = { + id = 6, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 7, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION"] = { + id = 8, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 9, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/latex.lua b/src/NotepadNext/languages/latex.lua new file mode 100644 index 000000000..f817c0262 --- /dev/null +++ b/src/NotepadNext/languages/latex.lua @@ -0,0 +1,86 @@ +local L = {} + +L.lexer = "latex" + +L.singleLineComment = "% " + +L.extensions = { + "tex", + "sty", +} + +L.keywords = { +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMAND"] = { + id = 1, + fgColor = rgb(0xAA0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TAG OPENING"] = { + id = 2, + fgColor = rgb(0x880088), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MATH INLINE"] = { + id = 3, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 4, + fgColor = rgb(0x00AA00), + bgColor = rgb(defaultBg), + }, + ["TAG CLOSING"] = { + id = 5, + fgColor = rgb(0x880088), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MATH BLOCK"] = { + id = 6, + fgColor = rgb(0x0000AA), + bgColor = rgb(defaultBg), + }, + ["COMMENT BLOCK"] = { + id = 7, + fgColor = rgb(0x00AA00), + bgColor = rgb(defaultBg), + }, + ["VERBATIM SEGMENT"] = { + id = 8, + fgColor = rgb(0x666666), + bgColor = rgb(defaultBg), + }, + ["SHORT COMMAND"] = { + id = 9, + fgColor = rgb(0xAA6600), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SPECIAL CHAR"] = { + id = 10, + fgColor = rgb(0xAAAA00), + bgColor = rgb(defaultBg), + }, + ["COMMAND OPTIONAL ARGUMENT"] = { + id = 11, + fgColor = rgb(0xFF9900), + bgColor = rgb(defaultBg), + }, + ["SYNTAX ERROR"] = { + id = 12, + fgColor = rgb(defaultBg), + bgColor = rgb(0xff0000), + }, +} +return L diff --git a/src/NotepadNext/languages/less.lua b/src/NotepadNext/languages/less.lua new file mode 100644 index 000000000..39f671a63 --- /dev/null +++ b/src/NotepadNext/languages/less.lua @@ -0,0 +1,93 @@ +local L = {} + +L.lexer = "css" + +L.singleLineComment = "// " + +L.extensions = { + "less", +} + +L.properties = { + ["lexer.css.less.language"] = "1", +} + +L.keywords = { + [0] = "-khtml-background-clip -khtml-background-origin -khtml-background-size -khtml-border-bottom-left-radius -khtml-border-bottom-right-radius -khtml-border-radius -khtml-border-top-left-radius -khtml-border-top-right-radius -khtml-opacity -moz-animation -moz-animation-delay -moz-animation-direction -moz-animation-duration -moz-animation-fill-mode -moz-animation-iteration-count -moz-animation-name -moz-animation-play-state -moz-animation-timing-function -moz-appearance -moz-background-clip -moz-background-inline-policy -moz-background-origin -moz-background-size -moz-binding -moz-border-bottom-colors -moz-border-end -moz-border-end-color -moz-border-end-style -moz-border-end-width -moz-border-image -moz-border-left-colors -moz-border-radius -moz-border-radius-bottomleft -moz-border-radius-bottomright -moz-border-radius-topleft -moz-border-radius-topright -moz-border-right-colors -moz-border-start -moz-border-start-color -moz-border-start-style -moz-border-start-width -moz-border-top-colors -moz-box-align -moz-box-direction -moz-box-flex -moz-box-flex-group -moz-box-flexgroup -moz-box-ordinal-group -moz-box-orient -moz-box-pack -moz-box-shadow -moz-box-sizing -moz-column-count -moz-column-gap -moz-column-rule -moz-column-rule-color -moz-column-rule-style -moz-column-rule-width -moz-column-width -moz-context-properties -moz-float-edge -moz-force-broken-image-icon -moz-image-region -moz-linear-gradient -moz-margin-end -moz-margin-start -moz-opacity -moz-outline -moz-outline-color -moz-outline-offset -moz-outline-radius -moz-outline-radius-bottomleft -moz-outline-radius-bottomright -moz-outline-radius-topleft -moz-outline-radius-topright -moz-outline-style -moz-outline-width -moz-padding-end -moz-padding-start -moz-radial-gradient -moz-stack-sizing -moz-text-decoration-color -moz-text-decoration-line -moz-text-decoration-style -moz-transform -moz-transform-origin -moz-transition -moz-transition-delay -moz-transition-duration -moz-transition-property -moz-transition-timing-function -moz-user-focus -moz-user-input -moz-user-modify -moz-user-select -moz-window-shadow -ms-filter -ms-transform -ms-transform-origin -o-transform -webkit-animation -webkit-animation-delay -webkit-animation-direction -webkit-animation-duration -webkit-animation-fill-mode -webkit-animation-iteration-count -webkit-animation-name -webkit-animation-play-state -webkit-animation-timing-function -webkit-appearance -webkit-backface-visibility -webkit-background-clip -webkit-background-composite -webkit-background-origin -webkit-background-size -webkit-border-bottom-left-radius -webkit-border-bottom-right-radius -webkit-border-horizontal-spacing -webkit-border-image -webkit-border-radius -webkit-border-top-left-radius -webkit-border-top-right-radius -webkit-border-vertical-spacing -webkit-box-align -webkit-box-direction -webkit-box-flex -webkit-box-flex-group -webkit-box-lines -webkit-box-ordinal-group -webkit-box-orient -webkit-box-pack -webkit-box-reflect -webkit-box-shadow -webkit-box-sizing -webkit-column-break-after -webkit-column-break-before -webkit-column-break-inside -webkit-column-count -webkit-column-gap -webkit-column-rule -webkit-column-rule-color -webkit-column-rule-style -webkit-column-rule-width -webkit-column-width -webkit-columns -webkit-dashboard-region -webkit-font-smoothing -webkit-gradient -webkit-line-break -webkit-linear-gradient -webkit-margin-bottom-collapse -webkit-margin-collapse -webkit-margin-start -webkit-margin-top-collapse -webkit-marquee -webkit-marquee-direction -webkit-marquee-increment -webkit-marquee-repetition -webkit-marquee-speed -webkit-marquee-style -webkit-mask -webkit-mask-attachment -webkit-mask-box-image -webkit-mask-clip -webkit-mask-composite -webkit-mask-image -webkit-mask-origin -webkit-mask-position -webkit-mask-position-x -webkit-mask-position-y -webkit-mask-repeat -webkit-mask-size -webkit-nbsp-mode -webkit-padding-start -webkit-perspective -webkit-perspective-origin -webkit-radial-gradient -webkit-rtl-ordering -webkit-tap-highlight-color -webkit-text-fill-color -webkit-text-security -webkit-text-size-adjust -webkit-text-stroke -webkit-text-stroke-color -webkit-text-stroke-width -webkit-touch-callout -webkit-transform -webkit-transform-origin -webkit-transform-origin-x -webkit-transform-origin-y -webkit-transform-origin-z -webkit-transform-style -webkit-transition -webkit-transition-delay -webkit-transition-duration -webkit-transition-property -webkit-transition-timing-function -webkit-user-drag -webkit-user-modify -webkit-user-select align-content align-items align-self alignment-adjust alignment-baseline all animation animation-delay animation-direction animation-duration animation-fill-mode animation-iteration-count animation-name animation-play-state animation-timing-function appearance azimuth backface-visibility background background-attachment background-blend-mode background-break background-clip background-color background-image background-origin background-position background-position-x background-position-y background-repeat background-size baseline-shift binding bleed block-size bookmark-label bookmark-level bookmark-state bookmark-target border border-block border-block-end border-block-start border-bottom border-bottom-color border-bottom-left-radius border-bottom-right-radius border-bottom-style border-bottom-width border-collapse border-color border-image border-image-outset border-image-repeat border-image-slice border-image-source border-image-width border-inline border-inline-end border-inline-end-width border-inline-start border-inline-start-color border-inline-start-style border-inline-start-width border-left border-left-color border-left-style border-left-width border-radius border-right border-right-color border-right-style border-right-width border-spacing border-style border-top border-top-color border-top-left-radius border-top-right-radius border-top-style border-top-width border-width bottom box-align box-decoration-break box-direction box-flex box-flex-group box-lines box-ordinal-group box-orient box-pack box-shadow box-sizing break-after break-before break-inside caption-side caret-color clear clip color color-profile column-count column-fill column-gap column-rule column-rule-color column-rule-style column-rule-width column-span column-width columns content counter-increment counter-reset crop cue cue-after cue-before cursor direction display dominant-baseline drop-initial-after-adjust drop-initial-after-align drop-initial-before-adjust drop-initial-before-align drop-initial-size drop-initial-value elevation empty-cells fill fill-opacity filter fit fit-position flex flex-basis flex-direction flex-flow flex-grow flex-shrink flex-wrap float float-offset font font-effect font-emphasize font-family font-size font-size-adjust font-stretch font-style font-variant font-variant-ligatures font-weight gap grid-area grid-auto-flow grid-auto-rows grid-column grid-column-end grid-column-gap grid-column-start grid-columns grid-gap grid-row grid-row-gap grid-rows grid-template-areas grid-template-columns grid-template-rows hanging-punctuation height hyphenate-after hyphenate-before hyphenate-character hyphenate-lines hyphenate-resource hyphens icon image-orientation image-rendering image-resolution inline-box-align inline-size inset inset-inline-end inset-inline-start justify-content justify-items justify-self left letter-spacing line-height line-stacking line-stacking-ruby line-stacking-shift line-stacking-strategy list-style list-style-image list-style-position list-style-type margin margin-block margin-block-end margin-block-start margin-bottom margin-inline margin-inline-end margin-inline-start margin-left margin-right margin-top mark mark-after mark-before marker-offset marks marquee-direction marquee-play-count marquee-speed marquee-style mask mask-clip mask-image mask-origin mask-position mask-position-x mask-repeat mask-size max-height max-width min-block-size min-height min-inline-size min-width mix-blend-mode move-to nav-down nav-index nav-left nav-right nav-up object-fit opacity order orphans outline outline-color outline-offset outline-style outline-width overflow overflow-anchor overflow-style overflow-wrap overflow-x overflow-y padding padding-block padding-block-end padding-block-start padding-bottom padding-inline padding-inline-end padding-inline-start padding-left padding-right padding-top page page-break-after page-break-before page-break-inside page-policy paint-order pause pause-after pause-before perspective perspective-origin phonemes pitch pitch-range play-during pointer-events position presentation-level punctuation-trim quotes rendering-intent resize rest rest-after rest-before richness right rotation rotation-point ruby-align ruby-overhang ruby-position ruby-span scrollbar-color size speak speak-header speak-numeral speak-punctuation speech-rate stress string-set stroke stroke-dasharray stroke-linejoin stroke-opacity stroke-width tab-size table-layout target target-name target-new target-position text-align text-align-last text-anchor text-decoration text-decoration-color text-decoration-line text-decoration-style text-emphasis text-height text-indent text-justify text-outline text-overflow text-rendering text-shadow text-transform text-wrap top transform transform-origin transform-style transition transition-delay transition-duration transition-property transition-timing-function unicode-bidi user-select vector-effect vertical-align visibility voice-balance voice-duration voice-family voice-pitch voice-pitch-range voice-rate voice-stress voice-volume volume white-space white-space-collapse widows width will-change word-break word-spacing word-wrap z-index", + [1] = "active after before check checked disabled empty enabled first first-child first-letter first-line first-of-type focus hover indeterminate invalid lang last-child last-of-type left link not nth-child nth-last-child nth-of-type nth-last-of-type only-child only-of-type optional read-only read-write required right root selection target valid visited", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["TAG"] = { + id = 1, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["CLASS"] = { + id = 2, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["PSEUDOCLASS"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["UNKNOWN_PSEUDOCLASS"] = { + id = 4, + fgColor = rgb(0xFF8080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 6, + fgColor = rgb(0x8080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["UNKNOWN_IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["VALUE"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 9, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["ID"] = { + id = 10, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IMPORTANT"] = { + id = 11, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DIRECTIVE"] = { + id = 12, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/lisp.lua b/src/NotepadNext/languages/lisp.lua new file mode 100644 index 000000000..3a72bb139 --- /dev/null +++ b/src/NotepadNext/languages/lisp.lua @@ -0,0 +1,78 @@ +local L = {} + +L.lexer = "lisp" + +L.singleLineComment = "; " + +L.extensions = { + "lsp", + "lisp", +} + +L.keywords = { + [0] = "not defun + - * / = < > <= >= princ eval apply funcall quote identity function complement backquote lambda set setq setf defmacro gensym make symbol intern name value plist get getf putprop remprop hash array aref car cdr caar cadr cdar cddr caaar caadr cadar caddr cdaar cdadr cddar cdddr caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr cons list append reverse last nth nthcdr member assoc subst sublis nsubst nsublis remove length mapc mapcar mapl maplist mapcan mapcon rplaca rplacd nconc delete atom symbolp numberp boundp null listp consp minusp zerop plusp evenp oddp eq eql equal cond case and or let l if prog prog1 prog2 progn go return do dolist dotimes catch throw error cerror break continue errset baktrace evalhook truncate float rem min max abs sin cos tan expt exp sqrt random logand logior logxor lognot bignums logeqv lognand lognor logorc2 logtest logbitp logcount integer nil", + [1] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENTLINE"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["FUNCTION WORD"] = { + id = 3, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION WORD2"] = { + id = 4, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SYMBOL"] = { + id = 5, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SPECIAL"] = { + id = 11, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 12, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/lua.lua b/src/NotepadNext/languages/lua.lua new file mode 100644 index 000000000..b8fd3596f --- /dev/null +++ b/src/NotepadNext/languages/lua.lua @@ -0,0 +1,106 @@ +local L = {} + +L.lexer = "lua" + +L.singleLineComment = "-- " + +L.extensions = { + "lua", +} + +L.keywords = { + [0] = "and break do else elseif end false for function goto if in local nil not or repeat return then true until while", + [1] = "_ENV _G _VERSION assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawlen rawset require select setfenv setmetatable tonumber tostring type unpack xpcall string table math bit32 coroutine io os debug package __index __newindex __call __add __sub __mul __div __mod __pow __unm __concat __len __eq __lt __le __gc __mode", + [2] = "byte char dump find format gmatch gsub len lower match rep reverse sub upper abs acos asin atan atan2 ceil cos cosh deg exp floor fmod frexp ldexp log log10 max min modf pow rad random randomseed sin sinh sqrt tan tanh arshift band bnot bor btest bxor extract lrotate lshift replace rrotate rshift shift string.byte string.char string.dump string.find string.format string.gmatch string.gsub string.len string.lower string.match string.rep string.reverse string.sub string.upper table.concat table.insert table.maxn table.pack table.remove table.sort table.unpack math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.cosh math.deg math.exp math.floor math.fmod math.frexp math.huge math.ldexp math.log math.log10 math.max math.min math.modf math.pi math.pow math.rad math.random math.randomseed math.sin math.sinh math.sqrt math.tan math.tanh bit32.arshift bit32.band bit32.bnot bit32.bor bit32.btest bit32.bxor bit32.extract bit32.lrotate bit32.lshift bit32.replace bit32.rrotate bit32.rshift", + [3] = "close flush lines read seek setvbuf write clock date difftime execute exit getenv remove rename setlocale time tmpname coroutine.create coroutine.resume coroutine.running coroutine.status coroutine.wrap coroutine.yield io.close io.flush io.input io.lines io.open io.output io.popen io.read io.tmpfile io.type io.write io.stderr io.stdin io.stdout os.clock os.date os.difftime os.execute os.exit os.getenv os.remove os.rename os.setlocale os.time os.tmpname debug.debug debug.getfenv debug.gethook debug.getinfo debug.getlocal debug.getmetatable debug.getregistry debug.getupvalue debug.getuservalue debug.setfenv debug.sethook debug.setlocal debug.setmetatable debug.setupvalue debug.setuservalue debug.traceback debug.upvalueid debug.upvaluejoin package.cpath package.loaded package.loaders package.loadlib package.path package.preload package.seeall", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["LITERALSTRING"] = { + id = 8, + fgColor = rgb(0x95004A), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNC1"] = { + id = 13, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNC2"] = { + id = 14, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNC3"] = { + id = 15, + fgColor = rgb(0x0000A0), + bgColor = rgb(defaultBg), + fontStyle = 3, + }, + ["IDENTIFIER"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 20, + fgColor = rgb(0x808000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/makefile.lua b/src/NotepadNext/languages/makefile.lua new file mode 100644 index 000000000..f6cb57ee7 --- /dev/null +++ b/src/NotepadNext/languages/makefile.lua @@ -0,0 +1,57 @@ +local L = {} + +L.lexer = "makefile" + +L.singleLineComment = "# " + +L.extensions = { + "mak", + "mk", +} + +L.keywords = { +} + + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 2, + fgColor = rgb(OperatorColor), + bgColor = rgb(0xC0C0C0), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 3, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TARGET"] = { + id = 5, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["IDEOL"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, +} + +return L diff --git a/src/NotepadNext/languages/markdown.lua b/src/NotepadNext/languages/markdown.lua new file mode 100644 index 000000000..905b7303c --- /dev/null +++ b/src/NotepadNext/languages/markdown.lua @@ -0,0 +1,132 @@ +local L = {} + +L.lexer = "markdown" + +L.disableFoldMargin = true + +L.extensions = { + "md", + "markdown", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["SCE_MARKDOWN_STRONG1"] = { + id = 2, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_STRONG2"] = { + id = 3, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_EM1"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["SCE_MARKDOWN_EM2"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["SCE_MARKDOWN_HEADER1"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_HEADER2"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_HEADER3"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_HEADER4"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_HEADER5"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_HEADER6"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_PRECHAR"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(0xEEEEAA), + }, + ["SCE_MARKDOWN_ULIST_ITEM"] = { + id = 13, + fgColor = rgb(0x555555), + bgColor = rgb(defaultBg), + }, + ["SCE_MARKDOWN_OLIST_ITEM"] = { + id = 14, + fgColor = rgb(0x555555), + bgColor = rgb(defaultBg), + }, + ["SCE_MARKDOWN_OLIST_ITEM"] = { + id = 15, + fgColor = rgb(0x000088), + bgColor = rgb(defaultBg), + }, + ["SCE_MARKDOWN_STRIKEOUT"] = { + id = 16, + fgColor = rgb(0x18453B), + bgColor = rgb(0xA9BA9D), + }, + ["SCE_MARKDOWN_HRULE"] = { + id = 17, + fgColor = rgb(0x555555), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SCE_MARKDOWN_LINK"] = { + id = 18, + fgColor = rgb(0x0000AA), + bgColor = rgb(defaultBg), + fontStyle = 4, + }, + ["SCE_MARKDOWN_CODE"] = { + id = 19, + fgColor = rgb(0x000088), + bgColor = rgb(0xEEEEEE), + }, + ["SCE_MARKDOWN_CODE2"] = { + id = 20, + fgColor = rgb(0x000088), + bgColor = rgb(0xEEEEEE), + }, + ["SCE_MARKDOWN_CODEBK"] = { + id = 20, + fgColor = rgb(0x000088), + bgColor = rgb(0xEEEEEE), + }, +} + +return L diff --git a/src/NotepadNext/languages/matlab.lua b/src/NotepadNext/languages/matlab.lua new file mode 100644 index 000000000..6c69c7f2f --- /dev/null +++ b/src/NotepadNext/languages/matlab.lua @@ -0,0 +1,64 @@ +local L = {} + +L.lexer = "matlab" + +L.singleLineComment = "% " + +L.extensions = { + "m", +} + +L.keywords = { + [0] = "break case catch classdef continue else elseif end for function global if otherwise parfor persistent return switch try while", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMAND"] = { + id = 2, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 4, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING"] = { + id = 5, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DOUBLE QUOTE STRING"] = { + id = 8, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/mmixal.lua b/src/NotepadNext/languages/mmixal.lua new file mode 100644 index 000000000..4c37394b7 --- /dev/null +++ b/src/NotepadNext/languages/mmixal.lua @@ -0,0 +1,111 @@ +local L = {} + +L.lexer = "mmixal" + +L.singleLineComment = "# " + +L.extensions = { + "mms", +} + +L.keywords = { + [0] = "2ADDU 4ADDU 8ADDU 16ADDU ADD ADDU AND ANDNH ANDNL ANDNMH ANDNML BDIF BEV BN BNN BNP BNZ BOD BP BSPEC BYTE BZ CMP CMPU CSEV CSN CSNN CSNP CSNZ CSOD CSP CSWAP CSZ DIV DIVU ESPEC EXPR FADD FCMP FCMPE FDIV FEQL FEQLE FIX FIXU FLOT FLOTU FMUL FREM FSQRT FSUB FUN FUNE GET GETA GO GREG I_BIT INCH INCL INCMH INCML IS JMP LDA LDB LDBU LDHT LDO LDOU LDSF LDT LDTU LDUNC LDVTS LDW LDWU LOC LOCAL MOR MUL MULU MUX MXOR NAND NEG NEGU NNIX NOR NXOR O_BIT OCTA ODIF OR ORH ORL ORMH ORML ORN PBEV PBN PBNN PBNP PBNZ PBOD PBP PBZ POP PREFIX PREGO PRELD PREST PUSHGO PUSHJ PUT RESUME SAVE SET SETH SETL SETMH SETML SFLOT SFLOTU SL SLU SR SRU STB STBU STCO STHT STO STOU STSF STT STTU STUNC STW STWU SUB SUBU SWYM SYNC SYNCD TDIF TETRA TRAP TRIP UNSAVE WDIF WYDEXOR ZSEV ZSN ZSNN ZSNP ZSNZ ZSOD ZSP ZSZ", + [1] = "rA rB rC rD rE rF rG rH rI rJ rK rL rM rN rO rP rQ rR rS rT rU rV rW rX rY rZ rBB rTT rWW rXX rYY rZZ", + [2] = "@ Text_Segment Data_Segment Pool_Segment Stack_Segment StdErr StdIn StdOut Fopen Fclose Fread Fwrite Fgets Fputs Fgetws Fputws Ftell Fseek TextRead TextWrite BinaryRead BinaryWrite BinaryReadWrite", +} + +L.styles = { + ["DIVSION OF LEADING WHITESPACE IN LINE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 2, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["OPCODE"] = { + id = 3, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DIVISION BETWEEN LABEL AND OPCODE"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["VALID OPCODE"] = { + id = 5, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["UNKNOWN OPCODE"] = { + id = 6, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["DIVISION BETWEEN OPCODE AND OPERANDS"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DIVISION OF OPERANDS"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 9, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["REFERENCE (TO A LABEL)"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CHAR"] = { + id = 11, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 12, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["REGISTER"] = { + id = 13, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["HEXADECIMAL NUMBER"] = { + id = 14, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 15, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SYMBOL"] = { + id = 16, + fgColor = rgb(0xFF7777), + bgColor = rgb(defaultBg), + }, + ["COMMENT OTHERWISE"] = { + id = 17, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/nfo.lua b/src/NotepadNext/languages/nfo.lua new file mode 100644 index 000000000..6a0d2df86 --- /dev/null +++ b/src/NotepadNext/languages/nfo.lua @@ -0,0 +1,19 @@ +local L = {} + +L.lexer = "nfo" + +L.extensions = { + "nfo", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 32, + fgColor = rgb(0x2E2E2E), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/nimrod.lua b/src/NotepadNext/languages/nimrod.lua new file mode 100644 index 000000000..5ef14e1e2 --- /dev/null +++ b/src/NotepadNext/languages/nimrod.lua @@ -0,0 +1,101 @@ +local L = {} + +L.lexer = "nimrod" + +L.singleLineComment = "! " + +L.extensions = { + "nim", +} + +L.keywords = { + [0] = "addr and as asm block break case cast const continue converter discard div elif else end enum except exception finally for from generic if implies import in include is isnot iterator lambda macro method mod nil not notin object of or out proc ptr raise ref return shl shr template try tuple type var when where while with without xor yield", +} + +L.styles = { + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 3, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["SINGLE QUOTED STRING"] = { + id = 4, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD"] = { + id = 5, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TRIPLE QUOTES"] = { + id = 6, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["TRIPLE DOUBLE QUOTES"] = { + id = 7, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["CLASS NAME DEFINITION"] = { + id = 8, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION OR METHOD NAME DEFINITION"] = { + id = 9, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATORS"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIERS"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT-BLOCKS"] = { + id = 12, + fgColor = rgb(0x7F7F7F), + bgColor = rgb(defaultBg), + }, + ["END OF LINE WHERE STRING IS NOT CLOSED"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(0xE0C0E0), + }, + ["HIGHLIGHTED IDENTIFIERS"] = { + id = 14, + fgColor = rgb(0x407090), + bgColor = rgb(defaultBg), + }, + ["DECORATORS"] = { + id = 15, + fgColor = rgb(0x805000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/nncrontab.lua b/src/NotepadNext/languages/nncrontab.lua new file mode 100644 index 000000000..2b8944b5d --- /dev/null +++ b/src/NotepadNext/languages/nncrontab.lua @@ -0,0 +1,79 @@ +local L = {} + +L.lexer = "nncrontab" + +L.singleLineComment = "# " + +L.extensions = { + "tab", + "spf", +} + +L.keywords = { + [0] = "AGAIN ALLOT AND Action BEGIN CASE COMPARE CONSTANT CREATE DO Days ELSE ENDCASE ENDOF EVAL-SUBST EVALUATE FALSE Hours I IF LEAVE LOOP Minutes Months NOT OF OFF ON OR PAD REPEAT Rule SET THEN TRUE Time UNTIL VALUE VARIABLE WHILE WeekDays Years", + [1] = " ACCESS-DATE BEEP CALL_DIAL CALL_HANGUP CHAR CLIPBOARD CONSOLE CREATION-DATE CUR-DATE DATE- DATE-INTERVAL DELAY DIAL DIR-CREATE DIR-DELETE DIR-EMPTY DIR-SIZE Day@ Domain ERR-MSG EXIST FILE-ACCESS-DATE FILE-APPEND FILE-COPY FILE-CREATE FILE-CREATION-DATE FILE-CROP FILE-DATE FILE-DELETE FILE-EMPTY FILE-EXIST FILE-MOVE FILE-RENAME FILE-SIZE FILE-WRITE FILE-WRITE-DATE FOR-CHILD-WINDOWS FOR-FILES FOR-WINDOWS FREE-SPACE GET-CUR-TIME GET-REG GET-VER GetTickCount HANGUP HIDE-ICON HINT HINT-OFF HINT-POS HINT-SIZE HINTW HOST-EXIST Hour@ IDLE INTERVAL IS-ARCHIVE IS-DIR IS-HIDDEN IS-READONLY IS-SYSTEM KILL LAUNCH LOG LOGGEDON LOGOFF LogonBatch LogonInteractive LogonNetwork MOUSE-LBCLK MOUSE-LBDCLK MOUSE-LBDN MOUSE-LBUP MOUSE-MOVE MOUSE-MOVER MOUSE-MOVEW MOUSE-RBCLK MOUSE-RBDCLK MOUSE-RBDN MOUSE-RBUP MSG Min@ Mon@ MonitorResponseTime NHOST-EXIST No ONLINE PAUSE PLAY-SOUND PLAY-SOUNDW POP3-CHECK POWEROFF PROC-EXIST PROC-TIME PURGE-OLD PURGE-OLDA PURGE-OLDW Password QSTART-APP QSTART-APPW QUERY QUIT RASDomain RASError RASPassword RASPhone RASSecPassword RASUser RE-ALL RE-MATCH REBOOT REG-DELETE-KEY REG-DELETE-VALUE REG-DWORD REG-SZ REMINDER RUN SEND-KEYS SEND-KEYS-DELAY SHOW-ICON SHUTDOWN START-APP START-APPW START-QUIT START-TIME Sec@ SecPassword THINT THINTW TimeSec@ TMSG TQUERY User WDay@ WIN-ACTIVATE WIN-ACTIVE WIN-CLICK WIN-CLOSE WIN-EXIST WIN-HIDE WIN-HWND WIN-MAXIMIZE WIN-MINIMIZE WIN-MOVE WIN-MOVER WIN-RESTORE WIN-SEND-KEYS WIN-SHOW WIN-TERMINATE WIN-TOPMOST WIN-VER WIN-WAIT WINAPI WRITE-DATE WatchClipboard WatchConnect WatchDir WatchDisconnect WatchDriveInsert WatchDriveRemove WatchFile WatchProc WatchProcStop WatchWinActivate WatchWinCreate WatchWinDestroy WatchWindow WinNT Year@ Yes", + [2] = "ALL AboveNormalPriority AsService BelowNormalPriority FILESONLY HighPriority IdlePriority LoadProfile NoActive NoDel NoLog NoRunAs NormalPriority OnceADay OnceAHour OnceAMonth OnceAWeek RECURSIVE RealtimePriority RunOnce SWHide ShowMaximized ShowMinimized ShowNoActivate ShowNormal StartIn StartPos StartSize TODEPTH WATCH-CHANGE-ATTRIBUTES WATCH-CHANGE-DIR-NAME WATCH-CHANGE-FILE-NAME WATCH-CHANGE-LAST-WRITE WATCH-CHANGE-SECURITY WATCH-CHANGE-SIZE WaitFor WatchSubtree WithoutProfile", +} + +L.styles = { + ["WHITESPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["TASK START/END"] = { + id = 2, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0x606060), + }, + ["SECTION KEYWORDS"] = { + id = 3, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["MODIFICATORS"] = { + id = 5, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["ASTERISK"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFFE0FF), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 7, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["DOUBLE QUOTED STRING"] = { + id = 8, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["ENVIRONMENT VARIABLE"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFFFFE0), + }, + ["IDENTIFIER"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFF0000), + }, +} +return L diff --git a/src/NotepadNext/languages/nsis.lua b/src/NotepadNext/languages/nsis.lua new file mode 100644 index 000000000..460622c53 --- /dev/null +++ b/src/NotepadNext/languages/nsis.lua @@ -0,0 +1,123 @@ +local L = {} + +L.lexer = "nsis" + +L.singleLineComment = "; " + +L.extensions = { + "nsi", + "nsh", +} + +L.keywords = { + [0] = "Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ChangeUI CheckBitmap ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exch Exec ExecShell ExecWait ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileReadUTF16LE FileSeek FileWrite FileWriteByte FileWriteUTF16LE FindClose FindFirst FindNext FindWindow FlushINI Function FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetExeName GetExePath GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LangStringUP LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LockWindow LogSet LogText ManifestDPIAware ManifestSupportedOS MessageBox MiscButtonText Nop Name OutFile Page PageEx PageExEnd PluginDir Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename RequestExecutionLevel ReserveFile Return RMDir SearchPath Section SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionGroup SectionGroupEnd SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressionLevel SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetPluginUnload SetRebootFlag SetRegView SetShellVarContext SetSilent SetStaticBkColor ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCmpS StrCpy StrLen SubSection SubSectionEnd Unicode UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL UnsafeStrCpy Var VIAddVersionKey VIFileVersion VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle !AddIncludeDir !AddPluginDir !appendfile !cd !define !delfile !echo !else !endif !error !execute !finalize !getdllversion !if !ifdef !ifmacrodef !ifmacrondef !ifndef !include !insertmacro !macro !macroend !macroundef !packhdr !searchparse !searchreplace !system !tempfile !undef !verbose !warning", + [1] = "$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $R0 $R1 $R2 $R3 $R4 $R5 $R6 $R7 $R8 $R9 $ADMINTOOLS $APPDATA $CDBURN_AREA $CMDLINE $COMMONFILES $COMMONFILES32 $COMMONFILES64 $COOKIES $DESKTOP $DOCUMENTS $EXEDIR $EXEFILE $EXEPATH $FAVORITES $FONTS $HISTORY $HWNDPARENT $INTERNET_CACHE $INSTDIR $LANGUAGE $LOCALAPPDATA $MUSIC $NETHOOD ${NSISDIR} $OUTDIR $PICTURES $PLUGINSDIR $PRINTHOOD $PROFILE $PROGRAMFILES $PROGRAMFILES32 $PROGRAMFILES64 $QUICKLAUNCH $RECENT $RESOURCES $RESOURCES_LOCALIZED $SENDTO $SMPROGRAMS $SMSTARTUP $STARTMENU $SYSDIR $TEMP $TEMPLATES $VIDEOS $WINDIR $$ $\n $\r $\t", + [2] = "ARCHIVE CUR END FILE_ATTRIBUTE_ARCHIVE FILE_ATTRIBUTE_HIDDEN FILE_ATTRIBUTE_NORMAL FILE_ATTRIBUTE_OFFLINE FILE_ATTRIBUTE_READONLY FILE_ATTRIBUTE_SYSTEM FILE_ATTRIBUTE_TEMPORARY HIDDEN HKCC HKCR HKCU HKDD HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG HKEY_CURRENT_USER HKEY_DYN_DATA HKEY_LOCAL_MACHINE HKEY_PERFORMANCE_DATA HKEY_USERS HKLM HKPD HKU IDABORT IDCANCEL IDIGNORE IDNO IDOK IDRETRY IDYES MB_ABORTRETRYIGNORE MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 MB_DEFBUTTON4 MB_ICONEXCLAMATION MB_ICONINFORMATION MB_ICONQUESTION MB_ICONSTOP MB_OK MB_OKCANCEL MB_RETRYCANCEL MB_RIGHT MB_SETFOREGROUND MB_TOPMOST MB_USERICON MB_YESNO MB_YESNOCANCEL NORMAL OFFLINE READONLY SET SHCTX SW_HIDE SW_SHOWMAXIMIZED SW_SHOWMINIMIZED SW_SHOWNORMAL SYSTEM TEMPORARY all auto both bottom bzip2 checkbox colored current false force hide ifdiff ifnewer lastused leave left listonly lzma nevershow none normal off on pop push radiobuttons right show silent silentlog smooth textonly top true try zlib", + [3] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENTLINE"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["STRING DOUBLE QUOTE"] = { + id = 2, + fgColor = rgb(0x808080), + bgColor = rgb(0xEEEEEE), + }, + ["STRING LEFT QUOTE"] = { + id = 3, + fgColor = rgb(OperatorColor), + bgColor = rgb(0xC0C0C0), + }, + ["STRING RIGHT QUOTE"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(0xC0C0C0), + }, + ["FUNCTION"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["VARIABLE"] = { + id = 6, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 7, + fgColor = rgb(0xFF0000), + bgColor = rgb(0xFFFF80), + }, + ["USER DEFINED"] = { + id = 8, + fgColor = rgb(0xFDFFEC), + bgColor = rgb(0xFF80FF), + fontStyle = 4, + }, + ["SECTION"] = { + id = 9, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SUBSECTION"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IF DEFINE"] = { + id = 11, + fgColor = rgb(0x808040), + bgColor = rgb(defaultBg), + }, + ["MACRO"] = { + id = 12, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING VAR"] = { + id = 13, + fgColor = rgb(0xFF8000), + bgColor = rgb(0xEFEFEF), + }, + ["NUMBER"] = { + id = 14, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["SECTION GROUP"] = { + id = 15, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PAGE EX"] = { + id = 16, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION DEFINITIONS"] = { + id = 17, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 18, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/objc.lua b/src/NotepadNext/languages/objc.lua new file mode 100644 index 000000000..3e59a37f8 --- /dev/null +++ b/src/NotepadNext/languages/objc.lua @@ -0,0 +1,116 @@ +local L = {} + +L.lexer = "objc" + +L.singleLineComment = "// " + +L.extensions = { + "mm", +} + +L.keywords = { + [0] = "if else switch case default break goto return for while do continue typedef sizeof NULL self super nil NIL", + [1] = "interface implementation protocol end private protected public class selector encode defs", + [2] = "void struct union enum char short int long double float signed unsigned const static extern auto register volatile id Class SEL IMP BOOL", + [3] = "oneway in out inout bycopy byref", +} + +L.styles = { + ["DIRECTIVE"] = { + id = 19, + fgColor = rgb(0xA001D6), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["QUALIFIER"] = { + id = 20, + fgColor = rgb(0x95004A), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/oscript.lua b/src/NotepadNext/languages/oscript.lua new file mode 100644 index 000000000..79ddcd72a --- /dev/null +++ b/src/NotepadNext/languages/oscript.lua @@ -0,0 +1,119 @@ +local L = {} + +L.lexer = "oscript" + +L.singleLineComment = "// " + +L.extensions = { + "osx", +} + +L.keywords = { + [0] = "break breakif by case continue continueif default downto else elseif end for goto if in repeat switch to until while function return void dll inbyref inout linked nodebug super this xcmd xfcn", + [1] = "false true undefined booleantype bytestype datatype dynamictype errortype externtype integertype listtype longtype objecttype objreftype pointtype realtype scripttype stringtype undefinedtype voidtype", + [2] = "and eq ge gt le lt ne not or xor", + [3] = "assoc boolean bytes date dynamic error extern file integer list long object point real recarray record script string cachetree capiconnect capierr capilog capilogin compiler dapisession dapinode dapiversion dapistream filecopy fileprefs frame javaobject mailmessage pop3session smtpsession ssloptions patfind patchange regex socket sqlconnection sqlcursor uapisession uapiuser wapisession wapimap wapimaptask wapiwork wapisubwork domattr domcdatasection domcharacterdata domcomment domdocument domdocumentfragment domdocumenttype domelement domentity domentityreference domimplementation domnamednodemap domnode domnodelist domnotation domparser domprocessinginstruction domtext saxparser xslprocessor", + [4] = "datatypename echo echodebug echoerror echoinfo echostamp echowarn getfeatures isdefined iserror isfeature isinvokable isnoterror isnotset isobject isset isundefined length nparameters parameters pointh pointv type", + [5] = "cachetree capiconnect capierr capilog capilogin compiler dapisession dapinode dapiversion dapistream filecopy fileprefs frame javaobject mailmessage pop3session smtpsession ssloptions patfind patchange regex socket sqlconnection sqlcursor uapisession uapiuser wapisession wapimap wapimaptask wapiwork wapisubwork domattr domcdatasection domcharacterdata domcomment domdocument domdocumentfragment domdocumenttype domelement domentity domentityreference domimplementation domnamednodemap domnode domnodelist domnotation domparser domprocessinginstruction domtext saxparser xslprocessor", +} + +L.styles = { + ["DEFAULT TEXT STYLE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["SINGLE-LINE COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["MULTI-LINE COMMENT"] = { + id = 2, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["#IFDEF DOC AND #ENDIF"] = { + id = 3, + fgColor = rgb(0x3F703F), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR DIRECTIVE"] = { + id = 4, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 5, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["STRING SINGLE QUOTES"] = { + id = 6, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["STRING DOUBLE QUOTES"] = { + id = 7, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["CONSTANT LITERAL"] = { + id = 8, + fgColor = rgb(0xFF7F3F), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["SERVER-GLOBAL VARIABLE (PREFIXED BY $)"] = { + id = 10, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["LANGUAGE NATIVE KEYWORD OR RESERVED WORD"] = { + id = 11, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATOR; EITHER SYMBOLIC OR LITERAL"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["LABEL TO JUMP TO WITH THE GOTO STATEMENT"] = { + id = 13, + fgColor = rgb(0xFF00FF), + bgColor = rgb(defaultBg), + }, + ["TYPE"] = { + id = 14, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["FUNCTION"] = { + id = 15, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["STATIC BUILT-IN OBJECT"] = { + id = 16, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["OBJECT PROPERTY"] = { + id = 17, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["OBJECT METHOD"] = { + id = 18, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/pascal.lua b/src/NotepadNext/languages/pascal.lua new file mode 100644 index 000000000..604060d88 --- /dev/null +++ b/src/NotepadNext/languages/pascal.lua @@ -0,0 +1,94 @@ +local L = {} + +L.lexer = "pascal" + +L.singleLineComment = "// " + +L.extensions = { + "pas", + "pp", + "p", + "inc", + "lpr", +} + +L.keywords = { + [0] = "and array asm begin case cdecl class const constructor default destructor div do downto else end end. except exit exports external far file finalization finally for function goto if implementation in index inherited initialization inline interface label library message mod near nil not object of on or out overload override packed pascal private procedure program property protected public published raise read record register repeat resourcestring safecall set shl shr stdcall stored string then threadvar to try type unit until uses var virtual while with write xor", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 1, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 3, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 4, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 5, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR2"] = { + id = 6, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 7, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["HEX NUMBER"] = { + id = 8, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 9, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING"] = { + id = 10, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 12, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 13, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["ASM"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/perl.lua b/src/NotepadNext/languages/perl.lua new file mode 100644 index 000000000..71c860c92 --- /dev/null +++ b/src/NotepadNext/languages/perl.lua @@ -0,0 +1,128 @@ +local L = {} + +L.lexer = "perl" + +L.singleLineComment = "# " + +L.first_line = { + "^#!.*perl" +} + +L.extensions = { + "pl", + "pm", + "plx", +} + +L.keywords = { + [0] = "ARGV AUTOLOAD Accept BEGIN Balloon Button CHECK CORE DATA DESTROY END Entry Frame INIT Label MainLoop Radiobutton STDERR STDIN STDOUT SUPER Tr UNITCHECK UNIVERSAL __DATA__ __END__ __FILE__ __LINE__ __PACKAGE__ __SUB__ abs accept address alarm and atan2 attach auth_type autoEscape bind binmode bless br break button caller caption chdir checkbox checkbox_group chmod chomp chop chown chr chroot close closedir cmp compile configure connect constant continue cookie cos crypt dbmclose dbmopen default defaults defined deiconify delete delete_all die div do dump each else elsif em end end_h1 end_html end_table end_ul endform endgrent endhostent endif endnetent endprotoent endpwent endservent eof eq escape escape_HTML eval evalbytes exec exists exit exp fc fcntl filefield fileno flock font for foreach fork format formline ge geometry getc getgrent getgrgid getgrnam getgrname gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername getpgrp getppid getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname getsockopt given glob gmtime goto grep groove gt h1 h2 h3 h4 h5 header hex hidden hr http https if image_button img import index insert int ioctl isindex join keys kill last lc lcfirst le length li link listen local localtime lock log lstat lt map maxsize minsize mkdir msgctl msgget msgrcv msgsnd multipart_end multipart_init multipart_start my ne next no not oct ol open opendir or ord our pack package param param_fetch password_field path_info pipe pop popup_menu pos pre print printf prototype push qq query_string quotemeta qw qx radio_group raise rand raw_cookie read readdir readline readlink readpipe recv redirect redo ref referer remote_addr remote_host remote_indent remote_user rename request_method require reset resizable return reverse rewinddir rindex rmdir say scalar script_name scrolling_list seek seekdir select self_url semctl semget semop send server_name server_port server_software set setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent setservent setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep socket socketpair sort span splice split sprintf sqrt srand start_form start_h1 start_html start_multipart_form start_table start_ul startform stat state strict strong study sub submit substr symlink syscall sysopen sysread sysseek system syswrite table tagConfigure td tell telldir textarea textfield th tie tied time times title tmpFileName top tr truncate uc ucfirst ul umask undef unescape unescapeHTML unless unlink unpack unshift untie until update upload uploadInfo url url_param use use_named_parameters user_agent user_name utime values variable vec virtual_host wait waitpid wantarray warn when while width write x xor", +} + +L.styles = { + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 0, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["REGEX"] = { + id = 17, + fgColor = rgb(0x8080FF), + bgColor = rgb(0xF8FEDE), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["SCALAR"] = { + id = 12, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["ARRAY"] = { + id = 13, + fgColor = rgb(0xCF34CF), + bgColor = rgb(defaultBg), + }, + ["HASH"] = { + id = 14, + fgColor = rgb(0x8080C0), + bgColor = rgb(defaultBg), + }, + ["SYMBOL TABLE"] = { + id = 15, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PUNCTUATION"] = { + id = 8, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["POD"] = { + id = 3, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["ERROR"] = { + id = 1, + fgColor = rgb(0xFF80C0), + bgColor = rgb(defaultBg), + fontStyle = 3, + }, + ["LONGQUOTE"] = { + id = 19, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["DATASECTION"] = { + id = 21, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["REGSUBST"] = { + id = 18, + fgColor = rgb(0x8080C0), + bgColor = rgb(0xFFEEEC), + }, + ["BACKTICKS"] = { + id = 20, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0x808080), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/php.lua b/src/NotepadNext/languages/php.lua new file mode 100644 index 000000000..9ce852eb0 --- /dev/null +++ b/src/NotepadNext/languages/php.lua @@ -0,0 +1,90 @@ +local L = {} + +L.lexer = "phpscript" + +L.singleLineComment = "// " + +L.extensions = { + "php", + "php3", + "php4", + "php5", + "phps", + "phpt", + "phtml", +} + +L.properties = { + ["fold.html"] = "1", +} + +L.keywords = { + [4] = "__autoload __class__ __compiler_halt_offset__ __construct __destruct __dir__ __file__ __function__ __halt_compiler __line__ __method__ __namespace__ __sleep __trait__ __wakeup _cookie _files _get _post abday_1 abday_2 abday_3 abday_4 abday_5 abday_6 abday_7 abmon_1 abmon_10 abmon_11 abmon_12 abmon_2 abmon_3 abmon_4 abmon_5 abmon_6 abmon_7 abmon_8 abmon_9 abs abstract acos acosh addcslashes addslashes af_inet af_inet6 af_unix al_bits al_buffer al_channels al_cone_inner_angle al_cone_outer_angle al_cone_outer_gain al_direction al_false al_format_mono16 al_format_mono8 al_format_stereo16 al_format_stereo8 al_frequency al_gain al_initial al_looping al_max_distance al_max_gain al_min_gain al_orientation al_paused al_pitch al_playing al_position al_reference_distance al_rolloff_factor al_size al_source_relative al_source_state al_stopped al_true al_velocity alc_frequency alc_refresh alc_sync alt_digits am_str and apache_child_terminate apache_get_modules apache_get_version apache_getenv apache_lookup_uri apache_map apache_note apache_request_headers apache_reset_timeout apache_response_headers apache_setenv apc_add apc_bin_dump apc_bin_dumpfile apc_bin_load apc_bin_loadfile apc_bin_verify_crc32 apc_bin_verify_md5 apc_cache_info apc_cas apc_clear_cache apc_compile_file apc_dec apc_define_constants apc_delete apc_delete_file apc_exists apc_fetch apc_inc apc_iter_all apc_iter_atime apc_iter_ctime apc_iter_device apc_iter_dtime apc_iter_filename apc_iter_inode apc_iter_key apc_iter_md5 apc_iter_mem_size apc_iter_mtime apc_iter_none apc_iter_num_hits apc_iter_refcount apc_iter_ttl apc_iter_type apc_iter_value apc_list_active apc_list_deleted apc_load_constants apc_sma_info apc_store apd_breakpoint apd_callstack apd_clunk apd_continue apd_croak apd_dump_function_table apd_dump_persistent_resources apd_dump_regular_resources apd_echo apd_get_active_symbols apd_set_pprof_trace apd_set_session apd_set_session_trace apd_set_session_trace_socket apd_version args_trace array array_change_key_case array_chunk array_column array_combine array_count_values array_diff array_diff_assoc array_diff_key array_diff_uassoc array_diff_ukey array_fill array_fill_keys array_filter array_filter_use_both array_filter_use_key array_flip array_intersect array_intersect_assoc array_intersect_key array_intersect_uassoc array_intersect_ukey array_key_exists array_keys array_map array_merge array_merge_recursive array_multisort array_pad array_pop array_product array_push array_rand array_reduce array_replace array_replace_recursive array_reverse array_search array_shift array_slice array_sort array_splice array_sum array_udiff array_udiff_assoc array_udiff_uassoc array_uintersect array_uintersect_assoc array_uintersect_uassoc array_unique array_unshift array_values array_walk array_walk_recursive arrayaccess arrayiterator arrayobject arsort as asin asinh asort assert assert_active assert_bail assert_callback assert_options assert_quiet_eval assert_warning assignment_trace atan atan2 atanh base64_decode base64_encode base_convert basename bbcode_add_element bbcode_add_smiley bbcode_arg_double_quote bbcode_arg_html_quote bbcode_arg_quote_escaping bbcode_arg_single_quote bbcode_auto_correct bbcode_correct_reopen_tags bbcode_create bbcode_default_smileys_off bbcode_default_smileys_on bbcode_destroy bbcode_disable_tree_build bbcode_flags_arg_parsing bbcode_flags_cdata_not_allowed bbcode_flags_deny_reopen_child bbcode_flags_one_open_per_level bbcode_flags_remove_if_empty bbcode_flags_smileys_off bbcode_flags_smileys_on bbcode_force_smileys_off bbcode_parse bbcode_set_arg_parser bbcode_set_flags bbcode_set_flags_add bbcode_set_flags_remove bbcode_set_flags_set bbcode_smileys_case_insensitive bbcode_type_arg bbcode_type_noarg bbcode_type_optarg bbcode_type_root bbcode_type_single bcadd bccomp bcdiv bcmod bcmul bcompiler_load bcompiler_load_exe bcompiler_parse_class bcompiler_read bcompiler_write_class bcompiler_write_constant bcompiler_write_exe_footer bcompiler_write_file bcompiler_write_footer bcompiler_write_function bcompiler_write_functions_from_file bcompiler_write_header bcompiler_write_included_filename bcpow bcpowmod bcscale bcsqrt bcsub bin2hex bind_textdomain_codeset bindec bindtextdomain blenc_encrypt blenc_ext_version bool boolean boolval break bson_decode bson_encode bus_adraln bus_adrerr bus_objerr bzclose bzcompress bzdecompress bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite cairo_antialias_default cairo_antialias_gray cairo_antialias_none cairo_antialias_subpixel cairo_content_alpha cairo_content_color cairo_content_color_alpha cairo_create cairo_extend_none cairo_extend_pad cairo_extend_reflect cairo_extend_repeat cairo_fill_rule_even_odd cairo_fill_rule_winding cairo_filter_best cairo_filter_bilinear cairo_filter_fast cairo_filter_gaussian cairo_filter_good cairo_filter_nearest cairo_font_face_get_type cairo_font_face_status cairo_font_options_create cairo_font_options_equal cairo_font_options_get_antialias cairo_font_options_get_hint_metrics cairo_font_options_get_hint_style cairo_font_options_get_subpixel_order cairo_font_options_hash cairo_font_options_merge cairo_font_options_set_antialias cairo_font_options_set_hint_metrics cairo_font_options_set_hint_style cairo_font_options_set_subpixel_order cairo_font_options_status cairo_font_slant_italic cairo_font_slant_normal cairo_font_slant_oblique cairo_font_type_ft cairo_font_type_quartz cairo_font_type_toy cairo_font_type_win32 cairo_font_weight_bold cairo_font_weight_normal cairo_format_a1 cairo_format_a8 cairo_format_argb32 cairo_format_rgb24 cairo_format_stride_for_width cairo_hint_metrics_default cairo_hint_metrics_off cairo_hint_metrics_on cairo_hint_style_default cairo_hint_style_full cairo_hint_style_medium cairo_hint_style_none cairo_hint_style_slight cairo_image_surface_create cairo_image_surface_create_for_data cairo_image_surface_create_from_png cairo_image_surface_get_data cairo_image_surface_get_format cairo_image_surface_get_height cairo_image_surface_get_stride cairo_image_surface_get_width cairo_line_cap_butt cairo_line_cap_round cairo_line_cap_square cairo_line_join_bevel cairo_line_join_miter cairo_line_join_round cairo_matrix_create_scale cairo_matrix_create_translate cairo_matrix_invert cairo_matrix_multiply cairo_matrix_rotate cairo_matrix_transform_distance cairo_matrix_transform_point cairo_matrix_translate cairo_operator_add cairo_operator_atop cairo_operator_clear cairo_operator_dest cairo_operator_dest_atop cairo_operator_dest_in cairo_operator_dest_out cairo_operator_dest_over cairo_operator_in cairo_operator_out cairo_operator_over cairo_operator_saturate cairo_operator_source cairo_operator_xor cairo_pattern_add_color_stop_rgb cairo_pattern_add_color_stop_rgba cairo_pattern_create_for_surface cairo_pattern_create_linear cairo_pattern_create_radial cairo_pattern_create_rgb cairo_pattern_create_rgba cairo_pattern_get_color_stop_count cairo_pattern_get_color_stop_rgba cairo_pattern_get_extend cairo_pattern_get_filter cairo_pattern_get_linear_points cairo_pattern_get_matrix cairo_pattern_get_radial_circles cairo_pattern_get_rgba cairo_pattern_get_surface cairo_pattern_get_type cairo_pattern_set_extend cairo_pattern_set_filter cairo_pattern_set_matrix cairo_pattern_status cairo_pattern_type_linear cairo_pattern_type_radial cairo_pattern_type_solid cairo_pattern_type_surface cairo_pdf_surface_create cairo_pdf_surface_set_size cairo_ps_get_levels cairo_ps_level_2 cairo_ps_level_3 cairo_ps_level_to_string cairo_ps_surface_create cairo_ps_surface_dsc_begin_page_setup cairo_ps_surface_dsc_begin_setup cairo_ps_surface_dsc_comment cairo_ps_surface_get_eps cairo_ps_surface_restrict_to_level cairo_ps_surface_set_eps cairo_ps_surface_set_size cairo_scaled_font_create cairo_scaled_font_extents cairo_scaled_font_get_ctm cairo_scaled_font_get_font_face cairo_scaled_font_get_font_matrix cairo_scaled_font_get_font_options cairo_scaled_font_get_scale_matrix cairo_scaled_font_get_type cairo_scaled_font_glyph_extents cairo_scaled_font_status cairo_scaled_font_text_extents cairo_status_clip_not_representable cairo_status_file_not_found cairo_status_invalid_content cairo_status_invalid_dash cairo_status_invalid_dsc_comment cairo_status_invalid_format cairo_status_invalid_index cairo_status_invalid_matrix cairo_status_invalid_path_data cairo_status_invalid_pop_group cairo_status_invalid_restore cairo_status_invalid_status cairo_status_invalid_stride cairo_status_invalid_string cairo_status_invalid_visual cairo_status_no_current_point cairo_status_no_memory cairo_status_null_pointer cairo_status_pattern_type_mismatch cairo_status_read_error cairo_status_success cairo_status_surface_finished cairo_status_surface_type_mismatch cairo_status_temp_file_error cairo_status_write_error cairo_subpixel_order_bgr cairo_subpixel_order_default cairo_subpixel_order_rgb cairo_subpixel_order_vbgr cairo_subpixel_order_vrgb cairo_surface_copy_page cairo_surface_create_similar cairo_surface_finish cairo_surface_flush cairo_surface_get_content cairo_surface_get_device_offset cairo_surface_get_font_options cairo_surface_get_type cairo_surface_mark_dirty cairo_surface_mark_dirty_rectangle cairo_surface_set_device_offset cairo_surface_set_fallback_resolution cairo_surface_show_page cairo_surface_status cairo_surface_type_beos cairo_surface_type_directfb cairo_surface_type_glitz cairo_surface_type_image cairo_surface_type_os2 cairo_surface_type_pdf cairo_surface_type_ps cairo_surface_type_quartz cairo_surface_type_quartz_image cairo_surface_type_svg cairo_surface_type_win32 cairo_surface_type_win32_printing cairo_surface_type_xcb cairo_surface_type_xlib cairo_surface_write_to_png cairo_svg_surface_create cairo_svg_surface_restrict_to_version cairo_svg_version_1_1 cairo_svg_version_1_2 cairo_svg_version_to_string cal_days_in_month cal_dow_dayno cal_dow_long cal_dow_short cal_easter_always_gregorian cal_easter_always_julian cal_easter_default cal_easter_roman cal_french cal_from_jd cal_gregorian cal_info cal_jewish cal_jewish_add_alafim cal_jewish_add_alafim_geresh cal_jewish_add_gereshayim cal_julian cal_month_french cal_month_gregorian_long cal_month_gregorian_short cal_month_jewish cal_month_julian_long cal_month_julian_short cal_num_cals cal_to_jd calcul_hmac calculhmac call_user_func call_user_func_array call_user_method call_user_method_array callable case case_lower case_upper catch ceil cfunction char_max chdb_create chdir checkdate checkdnsrr chgrp chmod chop chown chr chroot chunk_split cl_expunge class class_alias class_exists class_implements class_parents class_uses cld_continued cld_dumped cld_exited cld_killed cld_stopped cld_trapped clearstatcache cli_get_process_title cli_set_process_title clone closedir closelog clsctx_all clsctx_inproc_handler clsctx_inproc_server clsctx_local_server clsctx_remote_server clsctx_server codeset collator_asort collator_compare collator_create collator_get_attribute collator_get_error_code collator_get_error_message collator_get_locale collator_get_sort_key collator_get_strength collator_set_attribute collator_set_strength collator_sort collator_sort_with_sort_keys com_create_guid com_event_sink com_get com_get_active_object com_invoke com_load com_load_typelib com_message_pump com_print_typeinfo com_propget com_propput com_set compact connection_aborted connection_normal connection_status connection_timeout const constant continue convert_cyr_string convert_uudecode convert_uuencode copy cos cosh count count_chars count_normal count_recursive cp_acp cp_maccp cp_move cp_oemcp cp_symbol cp_thread_acp cp_uid cp_utf7 cp_utf8 crc32 create_function credits_all credits_docs credits_fullpage credits_general credits_group credits_modules credits_qa credits_sapi crncystr crypt crypt_blowfish crypt_ext_des crypt_md5 crypt_salt_length crypt_sha256 crypt_sha512 crypt_std_des ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_graph ctype_lower ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit cubrid_affected_rows cubrid_assoc cubrid_async cubrid_autocommit_false cubrid_autocommit_true cubrid_bind cubrid_both cubrid_client_encoding cubrid_close cubrid_close_prepare cubrid_close_request cubrid_col_get cubrid_col_size cubrid_column_names cubrid_column_types cubrid_commit cubrid_connect cubrid_connect_with_url cubrid_current_oid cubrid_cursor_current cubrid_cursor_error cubrid_cursor_first cubrid_cursor_last cubrid_cursor_success cubrid_data_seek cubrid_db_name cubrid_disconnect cubrid_drop cubrid_errno cubrid_error cubrid_error_code cubrid_error_code_facility cubrid_error_msg cubrid_exec_query_all cubrid_execute cubrid_facility_cas cubrid_facility_cci cubrid_facility_client cubrid_facility_dbms cubrid_fetch cubrid_fetch_array cubrid_fetch_assoc cubrid_fetch_field cubrid_fetch_lengths cubrid_fetch_object cubrid_fetch_row cubrid_field_flags cubrid_field_len cubrid_field_name cubrid_field_seek cubrid_field_table cubrid_field_type cubrid_free_result cubrid_get cubrid_get_autocommit cubrid_get_charset cubrid_get_class_name cubrid_get_client_info cubrid_get_db_parameter cubrid_get_query_timeout cubrid_get_server_info cubrid_include_oid cubrid_insert_id cubrid_is_instance cubrid_list_dbs cubrid_lob cubrid_lob2_bind cubrid_lob2_close cubrid_lob2_export cubrid_lob2_import cubrid_lob2_new cubrid_lob2_read cubrid_lob2_seek cubrid_lob2_seek64 cubrid_lob2_size cubrid_lob2_size64 cubrid_lob2_tell cubrid_lob2_tell64 cubrid_lob2_write cubrid_lob_close cubrid_lob_export cubrid_lob_get cubrid_lob_send cubrid_lob_size cubrid_lock_read cubrid_lock_write cubrid_move_cursor cubrid_next_result cubrid_no_more_data cubrid_num cubrid_num_cols cubrid_num_fields cubrid_num_rows cubrid_object cubrid_param_isolation_level cubrid_param_lock_timeout cubrid_pconnect cubrid_pconnect_with_url cubrid_ping cubrid_prepare cubrid_put cubrid_query cubrid_real_escape_string cubrid_result cubrid_rollback cubrid_sch_attr_privilege cubrid_sch_attribute cubrid_sch_class cubrid_sch_class_attribute cubrid_sch_class_method cubrid_sch_class_privilege cubrid_sch_constraint cubrid_sch_cross_reference cubrid_sch_direct_super_class cubrid_sch_exported_keys cubrid_sch_imported_keys cubrid_sch_method cubrid_sch_method_file cubrid_sch_primary_key cubrid_sch_query_spec cubrid_sch_subclass cubrid_sch_superclass cubrid_sch_trigger cubrid_sch_vclass cubrid_schema cubrid_seq_drop cubrid_seq_insert cubrid_seq_put cubrid_set_add cubrid_set_autocommit cubrid_set_db_parameter cubrid_set_drop cubrid_set_query_timeout cubrid_unbuffered_query cubrid_version curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_fnmatchfunc_fail curl_fnmatchfunc_match curl_fnmatchfunc_nomatch curl_getinfo curl_http_version_1_0 curl_http_version_1_1 curl_http_version_2_0 curl_http_version_none curl_init curl_ipresolve_v4 curl_ipresolve_v6 curl_ipresolve_whatever curl_lock_data_cookie curl_lock_data_dns curl_lock_data_ssl_session curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_netrc_ignored curl_netrc_optional curl_netrc_required curl_pause curl_readfunc_pause curl_reset curl_rtspreq_announce curl_rtspreq_describe curl_rtspreq_get_parameter curl_rtspreq_options curl_rtspreq_pause curl_rtspreq_play curl_rtspreq_receive curl_rtspreq_record curl_rtspreq_set_parameter curl_rtspreq_setup curl_rtspreq_teardown curl_setopt curl_setopt_array curl_share_close curl_share_init curl_share_setopt curl_sslversion_default curl_sslversion_sslv2 curl_sslversion_sslv3 curl_sslversion_tlsv1 curl_sslversion_tlsv1_0 curl_sslversion_tlsv1_1 curl_sslversion_tlsv1_2 curl_strerror curl_timecond_ifmodsince curl_timecond_ifunmodsince curl_timecond_lastmod curl_timecond_none curl_tlsauth_srp curl_unescape curl_version curl_version_http2 curl_version_ipv6 curl_version_kerberos4 curl_version_libz curl_version_ssl curl_wrappers_enabled curl_writefunc_pause curlauth_any curlauth_anysafe curlauth_basic curlauth_digest curlauth_digest_ie curlauth_gssnegotiate curlauth_none curlauth_ntlm curlauth_only curlclosepolicy_callback curlclosepolicy_least_recently_used curlclosepolicy_least_traffic curlclosepolicy_oldest curlclosepolicy_slowest curle_aborted_by_callback curle_bad_calling_order curle_bad_content_encoding curle_bad_download_resume curle_bad_function_argument curle_bad_password_entered curle_couldnt_connect curle_couldnt_resolve_host curle_couldnt_resolve_proxy curle_failed_init curle_file_couldnt_read_file curle_filesize_exceeded curle_ftp_access_denied curle_ftp_bad_download_resume curle_ftp_cant_get_host curle_ftp_cant_reconnect curle_ftp_couldnt_get_size curle_ftp_couldnt_retr_file curle_ftp_couldnt_set_ascii curle_ftp_couldnt_set_binary curle_ftp_couldnt_stor_file curle_ftp_couldnt_use_rest curle_ftp_partial_file curle_ftp_port_failed curle_ftp_quote_error curle_ftp_ssl_failed curle_ftp_user_password_incorrect curle_ftp_weird_227_format curle_ftp_weird_pass_reply curle_ftp_weird_pasv_reply curle_ftp_weird_server_reply curle_ftp_weird_user_reply curle_ftp_write_error curle_function_not_found curle_got_nothing curle_http_not_found curle_http_port_failed curle_http_post_error curle_http_range_error curle_http_returned_error curle_ldap_cannot_bind curle_ldap_invalid_url curle_ldap_search_failed curle_library_not_found curle_malformat_user curle_obsolete curle_ok curle_operation_timedout curle_operation_timeouted curle_out_of_memory curle_partial_file curle_read_error curle_recv_error curle_send_error curle_share_in_use curle_ssh curle_ssl_cacert curle_ssl_certproblem curle_ssl_cipher curle_ssl_connect_error curle_ssl_engine_notfound curle_ssl_engine_setfailed curle_ssl_peer_certificate curle_telnet_option_syntax curle_too_many_redirects curle_unknown_telnet_option curle_unsupported_protocol curle_url_malformat curle_url_malformat_user curle_write_error curlftpauth_default curlftpauth_ssl curlftpauth_tls curlftpmethod_multicwd curlftpmethod_nocwd curlftpmethod_singlecwd curlftpssl_all curlftpssl_ccc_active curlftpssl_ccc_none curlftpssl_ccc_passive curlftpssl_control curlftpssl_none curlftpssl_try curlgssapi_delegation_flag curlgssapi_delegation_policy_flag curlinfo_appconnect_time curlinfo_certinfo curlinfo_condition_unmet curlinfo_connect_time curlinfo_content_length_download curlinfo_content_length_upload curlinfo_content_type curlinfo_cookielist curlinfo_effective_url curlinfo_filetime curlinfo_ftp_entry_path curlinfo_header_out curlinfo_header_size curlinfo_http_code curlinfo_http_connectcode curlinfo_httpauth_avail curlinfo_lastone curlinfo_local_ip curlinfo_local_port curlinfo_namelookup_time curlinfo_num_connects curlinfo_os_errno curlinfo_pretransfer_time curlinfo_primary_ip curlinfo_primary_port curlinfo_private curlinfo_proxyauth_avail curlinfo_redirect_count curlinfo_redirect_time curlinfo_redirect_url curlinfo_request_size curlinfo_response_code curlinfo_rtsp_client_cseq curlinfo_rtsp_cseq_recv curlinfo_rtsp_server_cseq curlinfo_rtsp_session_id curlinfo_size_download curlinfo_size_upload curlinfo_speed_download curlinfo_speed_upload curlinfo_ssl_engines curlinfo_ssl_verifyresult curlinfo_starttransfer_time curlinfo_total_time curlm_bad_easy_handle curlm_bad_handle curlm_call_multi_perform curlm_internal_error curlm_ok curlm_out_of_memory curlmopt_maxconnects curlmopt_pipelining curlmsg_done curlopt_accept_encoding curlopt_accepttimeout_ms curlopt_address_scope curlopt_append curlopt_autoreferer curlopt_binarytransfer curlopt_buffersize curlopt_cainfo curlopt_capath curlopt_certinfo curlopt_closepolicy curlopt_connect_only curlopt_connecttimeout curlopt_connecttimeout_ms curlopt_cookie curlopt_cookiefile curlopt_cookiejar curlopt_cookielist curlopt_cookiesession curlopt_crlf curlopt_crlfile curlopt_customrequest curlopt_dirlistonly curlopt_dns_cache_timeout curlopt_dns_servers curlopt_dns_use_global_cache curlopt_egdsocket curlopt_encoding curlopt_failonerror curlopt_file curlopt_filetime curlopt_fnmatch_function curlopt_followlocation curlopt_forbid_reuse curlopt_fresh_connect curlopt_ftp_account curlopt_ftp_alternative_to_user curlopt_ftp_create_missing_dirs curlopt_ftp_filemethod curlopt_ftp_response_timeout curlopt_ftp_skip_pasv_ip curlopt_ftp_ssl curlopt_ftp_ssl_ccc curlopt_ftp_use_eprt curlopt_ftp_use_epsv curlopt_ftp_use_pret curlopt_ftpappend curlopt_ftpascii curlopt_ftplistonly curlopt_ftpport curlopt_ftpsslauth curlopt_gssapi_delegation curlopt_header curlopt_headerfunction curlopt_http200aliases curlopt_http_content_decoding curlopt_http_transfer_decoding curlopt_http_version curlopt_httpauth curlopt_httpget curlopt_httpheader curlopt_httpproxytunnel curlopt_ignore_content_length curlopt_infile curlopt_infilesize curlopt_interface curlopt_ipresolve curlopt_issuercert curlopt_keypasswd curlopt_krb4level curlopt_krblevel curlopt_localport curlopt_localportrange curlopt_low_speed_limit curlopt_low_speed_time curlopt_mail_auth curlopt_mail_from curlopt_mail_rcpt curlopt_max_recv_speed_large curlopt_max_send_speed_large curlopt_maxconnects curlopt_maxfilesize curlopt_maxredirs curlopt_mute curlopt_netrc curlopt_netrc_file curlopt_new_directory_perms curlopt_new_file_perms curlopt_nobody curlopt_noprogress curlopt_noproxy curlopt_nosignal curlopt_passwdfunction curlopt_password curlopt_port curlopt_post curlopt_postfields curlopt_postquote curlopt_postredir curlopt_prequote curlopt_private curlopt_progressfunction curlopt_protocols curlopt_proxy curlopt_proxy_transfer_mode curlopt_proxyauth curlopt_proxypassword curlopt_proxyport curlopt_proxytype curlopt_proxyusername curlopt_proxyuserpwd curlopt_put curlopt_quote curlopt_random_file curlopt_range curlopt_readdata curlopt_readfunction curlopt_redir_protocols curlopt_referer curlopt_resolve curlopt_resume_from curlopt_returntransfer curlopt_rtsp_client_cseq curlopt_rtsp_request curlopt_rtsp_server_cseq curlopt_rtsp_session_id curlopt_rtsp_stream_uri curlopt_rtsp_transport curlopt_safe_upload curlopt_share curlopt_socks5_gssapi_nec curlopt_socks5_gssapi_service curlopt_ssh_auth_types curlopt_ssh_host_public_key_md5 curlopt_ssh_knownhosts curlopt_ssh_private_keyfile curlopt_ssh_public_keyfile curlopt_ssl_cipher_list curlopt_ssl_options curlopt_ssl_sessionid_cache curlopt_ssl_verifyhost curlopt_ssl_verifypeer curlopt_sslcert curlopt_sslcertpasswd curlopt_sslcerttype curlopt_sslengine curlopt_sslengine_default curlopt_sslkey curlopt_sslkeypasswd curlopt_sslkeytype curlopt_sslversion curlopt_stderr curlopt_tcp_keepalive curlopt_tcp_keepidle curlopt_tcp_keepintvl curlopt_tcp_nodelay curlopt_telnetoptions curlopt_tftp_blksize curlopt_timecondition curlopt_timeout curlopt_timeout_ms curlopt_timevalue curlopt_tlsauth_password curlopt_tlsauth_type curlopt_tlsauth_username curlopt_transfer_encoding curlopt_transfertext curlopt_unrestricted_auth curlopt_upload curlopt_url curlopt_use_ssl curlopt_useragent curlopt_username curlopt_userpwd curlopt_verbose curlopt_wildcardmatch curlopt_writefunction curlopt_writeheader curlpause_all curlpause_cont curlpause_recv curlpause_recv_cont curlpause_send curlpause_send_cont curlproto_all curlproto_dict curlproto_file curlproto_ftp curlproto_ftps curlproto_gopher curlproto_http curlproto_https curlproto_imap curlproto_imaps curlproto_ldap curlproto_ldaps curlproto_pop3 curlproto_pop3s curlproto_rtmp curlproto_rtmpe curlproto_rtmps curlproto_rtmpt curlproto_rtmpte curlproto_rtmpts curlproto_rtsp curlproto_scp curlproto_sftp curlproto_smtp curlproto_smtps curlproto_telnet curlproto_tftp curlproxy_http curlproxy_socks4 curlproxy_socks4a curlproxy_socks5 curlproxy_socks5_hostname curlshopt_none curlshopt_share curlshopt_unshare curlssh_auth_any curlssh_auth_default curlssh_auth_host curlssh_auth_keyboard curlssh_auth_none curlssh_auth_password curlssh_auth_publickey curlsslopt_allow_beast curlusessl_all curlusessl_control curlusessl_none curlusessl_try curlversion_now currency_symbol current cyrus_authenticate cyrus_bind cyrus_callback_noliteral cyrus_callback_numbered cyrus_close cyrus_conn_initialresponse cyrus_conn_nonsyncliteral cyrus_connect cyrus_query cyrus_unbind d_fmt d_t_fmt date date_add date_atom date_cookie date_create date_create_from_format date_create_immutable date_create_immutable_from_format date_date_set date_default_timezone_get date_default_timezone_set date_diff date_format date_get_last_errors date_interval_create_from_date_string date_interval_format date_iso8601 date_isodate_set date_modify date_offset_get date_parse date_parse_from_format date_rfc1036 date_rfc1123 date_rfc2822 date_rfc3339 date_rfc822 date_rfc850 date_rss date_sub date_sun_info date_sunrise date_sunset date_time_set date_timestamp_get date_timestamp_set date_timezone_get date_timezone_set date_w3c datefmt_create datefmt_format datefmt_get_calendar datefmt_get_datetype datefmt_get_error_code datefmt_get_error_message datefmt_get_locale datefmt_get_pattern datefmt_get_timetype datefmt_get_timezone_id datefmt_is_lenient datefmt_localtime datefmt_parse datefmt_set_calendar datefmt_set_lenient datefmt_set_pattern datefmt_set_timezone_id day_1 day_2 day_3 day_4 day_5 day_6 day_7 db2_autocommit db2_autocommit_off db2_autocommit_on db2_binary db2_bind_param db2_case_lower db2_case_natural db2_case_upper db2_char db2_client_info db2_close db2_column_privileges db2_columns db2_commit db2_conn_error db2_conn_errormsg db2_connect db2_convert db2_cursor_type db2_deferred_prepare_off db2_deferred_prepare_on db2_double db2_escape_string db2_exec db2_execute db2_fetch_array db2_fetch_assoc db2_fetch_both db2_fetch_object db2_fetch_row db2_field_display_size db2_field_name db2_field_num db2_field_precision db2_field_scale db2_field_type db2_field_width db2_foreign_keys db2_forward_only db2_free_result db2_free_stmt db2_get_option db2_last_insert_id db2_lob_read db2_long db2_next_result db2_num_fields db2_num_rows db2_param_file db2_param_in db2_param_inout db2_param_out db2_passthru db2_pclose db2_pconnect db2_prepare db2_primary_keys db2_procedure_columns db2_procedures db2_result db2_rollback db2_scrollable db2_server_info db2_set_option db2_special_columns db2_statistics db2_stmt_error db2_stmt_errormsg db2_table_privileges db2_tables dba_close dba_delete dba_exists dba_fetch dba_firstkey dba_handlers dba_insert dba_key_split dba_list dba_nextkey dba_open dba_optimize dba_popen dba_replace dba_sync dbase_add_record dbase_close dbase_create dbase_delete_record dbase_get_header_info dbase_get_record dbase_get_record_with_names dbase_numfields dbase_numrecords dbase_open dbase_pack dbase_replace_record dbplus_add dbplus_aql dbplus_chdir dbplus_close dbplus_curr dbplus_err_close dbplus_err_corrupt_tuple dbplus_err_crc dbplus_err_create dbplus_err_dbparse dbplus_err_dbpreexit dbplus_err_dbrunerr dbplus_err_duplicate dbplus_err_empty dbplus_err_eoscan dbplus_err_fifo dbplus_err_length dbplus_err_locked dbplus_err_lseek dbplus_err_magic dbplus_err_malloc dbplus_err_nidx dbplus_err_noerr dbplus_err_nolock dbplus_err_nusers dbplus_err_ontrap dbplus_err_open dbplus_err_panic dbplus_err_perm dbplus_err_pgsize dbplus_err_pipe dbplus_err_preexit dbplus_err_preproc dbplus_err_read dbplus_err_restricted dbplus_err_tcl dbplus_err_unknown dbplus_err_user dbplus_err_version dbplus_err_wait dbplus_err_warning0 dbplus_err_wlocked dbplus_err_wopen dbplus_err_write dbplus_errcode dbplus_errno dbplus_find dbplus_first dbplus_flush dbplus_freealllocks dbplus_freelock dbplus_freerlocks dbplus_getlock dbplus_getunique dbplus_info dbplus_last dbplus_lockrel dbplus_next dbplus_open dbplus_prev dbplus_rchperm dbplus_rcreate dbplus_rcrtexact dbplus_rcrtlike dbplus_resolve dbplus_restorepos dbplus_rkeys dbplus_ropen dbplus_rquery dbplus_rrename dbplus_rsecindex dbplus_runlink dbplus_rzap dbplus_savepos dbplus_setindex dbplus_setindexbynumber dbplus_sql dbplus_tcl dbplus_tremove dbplus_undo dbplus_undoprepare dbplus_unlockrel dbplus_unselect dbplus_update dbplus_xlockrel dbplus_xunlockrel dbx_close dbx_cmp_asc dbx_cmp_desc dbx_cmp_native dbx_cmp_number dbx_cmp_text dbx_colnames_lowercase dbx_colnames_unchanged dbx_colnames_uppercase dbx_compare dbx_connect dbx_error dbx_escape_string dbx_fbsql dbx_fetch_row dbx_mssql dbx_mysql dbx_oci8 dbx_odbc dbx_persistent dbx_pgsql dbx_query dbx_result_assoc dbx_result_index dbx_result_info dbx_result_unbuffered dbx_sort dbx_sqlite dbx_sybasect dcgettext dcngettext debug_backtrace debug_backtrace_ignore_args debug_backtrace_provide_object debug_print_backtrace debug_zval_dump decbin dechex decimal_point declare decoct default default_include_path define define_syslog_variables defined deg2rad delete dgettext die dio_close dio_fcntl dio_open dio_read dio_seek dio_stat dio_tcsetattr dio_truncate dio_write dir directory directory_separator dirname disk_free_space disk_total_space diskfreespace disp_e_badindex disp_e_divbyzero disp_e_overflow dl dngettext dns_a dns_a6 dns_aaaa dns_all dns_any dns_check_record dns_cname dns_get_mx dns_get_record dns_hinfo dns_mx dns_naptr dns_ns dns_ptr dns_soa dns_srv dns_txt do dom_hierarchy_request_err dom_import_simplexml dom_index_size_err dom_inuse_attribute_err dom_invalid_access_err dom_invalid_character_err dom_invalid_modification_err dom_invalid_state_err dom_namespace_err dom_no_data_allowed_err dom_no_modification_allowed_err dom_not_found_err dom_not_supported_err dom_php_err dom_syntax_err dom_validation_err dom_wrong_document_err domstring_size_err double doubleval e_all e_compile_error e_compile_warning e_core_error e_core_warning e_deprecated e_error e_notice e_parse e_recoverable_error e_strict e_user_deprecated e_user_error e_user_notice e_user_warning e_warning each easter_date easter_days echo eio_busy eio_cancel eio_chmod eio_chown eio_close eio_custom eio_dt_blk eio_dt_chr eio_dt_cmp eio_dt_dir eio_dt_door eio_dt_fifo eio_dt_lnk eio_dt_max eio_dt_mpb eio_dt_mpc eio_dt_nam eio_dt_nwk eio_dt_reg eio_dt_sock eio_dt_unknown eio_dt_wht eio_dup2 eio_event_loop eio_falloc_fl_keep_size eio_fallocate eio_fchmod eio_fchown eio_fdatasync eio_fstat eio_fstatvfs eio_fsync eio_ftruncate eio_futime eio_get_event_stream eio_get_last_error eio_grp eio_grp_add eio_grp_cancel eio_grp_limit eio_init eio_link eio_lstat eio_mkdir eio_mknod eio_nop eio_npending eio_nready eio_nreqs eio_nthreads eio_o_append eio_o_creat eio_o_excl eio_o_fsync eio_o_nonblock eio_o_rdonly eio_o_rdwr eio_o_trunc eio_o_wronly eio_open eio_poll eio_pri_default eio_pri_max eio_pri_min eio_read eio_readahead eio_readdir eio_readdir_dents eio_readdir_dirs_first eio_readdir_found_unknown eio_readdir_stat_order eio_readlink eio_realpath eio_rename eio_rmdir eio_s_ifblk eio_s_ifchr eio_s_ififo eio_s_ifreg eio_s_ifsock eio_s_irgrp eio_s_iroth eio_s_irusr eio_s_iwgrp eio_s_iwoth eio_s_iwusr eio_s_ixgrp eio_s_ixoth eio_s_ixusr eio_seek eio_seek_cur eio_seek_end eio_seek_set eio_sendfile eio_set_max_idle eio_set_max_parallel eio_set_max_poll_reqs eio_set_max_poll_time eio_set_min_parallel eio_stat eio_statvfs eio_symlink eio_sync eio_sync_file_range eio_sync_file_range_wait_after eio_sync_file_range_wait_before eio_sync_file_range_write eio_syncfs eio_truncate eio_unlink eio_utime eio_write else elseif empty enc7bit enc8bit encbase64 encbinary encother encquotedprintable end enddeclare endfor endforeach endif endswitch endwhile ent_compat ent_disallowed ent_html401 ent_html5 ent_ignore ent_noquotes ent_quotes ent_substitute ent_xhtml ent_xml1 era era_d_fmt era_d_t_fmt era_t_fmt era_year ereg ereg_replace eregi eregi_replace error_clear_last error_get_last error_log error_reporting error_trace escapeshellarg escapeshellcmd ev_persist ev_read ev_signal ev_timeout ev_write eval event_add event_base_free event_base_loop event_base_loopbreak event_base_loopexit event_base_new event_base_priority_init event_base_reinit event_base_set event_buffer_base_set event_buffer_disable event_buffer_enable event_buffer_fd_set event_buffer_free event_buffer_new event_buffer_priority_set event_buffer_read event_buffer_set_callback event_buffer_timeout_set event_buffer_watermark_set event_buffer_write event_del event_free event_new event_priority_set event_set event_timer_add event_timer_del event_timer_new event_timer_set evloop_nonblock evloop_once exec exif_imagetype exif_read_data exif_tagname exif_thumbnail exif_use_mbstring exit exp exp_eof exp_exact exp_fullbuffer exp_glob exp_regexp exp_timeout expect_expectl expect_popen explode expm1 extends extension_loaded extr_if_exists extr_overwrite extr_prefix_all extr_prefix_if_exists extr_prefix_invalid extr_prefix_same extr_refs extr_skip extract ezmlm_hash f_dupfd f_getfd f_getfl f_getlk f_getown f_rdlck f_setfl f_setlk f_setlkw f_setown f_unlck f_wrlck false fann_cascadetrain_on_data fann_cascadetrain_on_file fann_clear_scaling_params fann_copy fann_cos fann_cos_symmetric fann_create_from_file fann_create_shortcut fann_create_shortcut_array fann_create_sparse fann_create_sparse_array fann_create_standard fann_create_standard_array fann_create_train fann_create_train_from_callback fann_descale_input fann_descale_output fann_descale_train fann_destroy fann_destroy_train fann_duplicate_train_data fann_e_cant_allocate_mem fann_e_cant_open_config_r fann_e_cant_open_config_w fann_e_cant_open_td_r fann_e_cant_open_td_w fann_e_cant_read_config fann_e_cant_read_connections fann_e_cant_read_neuron fann_e_cant_read_td fann_e_cant_train_activation fann_e_cant_use_activation fann_e_cant_use_train_alg fann_e_index_out_of_bound fann_e_input_no_match fann_e_no_error fann_e_output_no_match fann_e_scale_not_present fann_e_train_data_mismatch fann_e_train_data_subset fann_e_wrong_config_version fann_e_wrong_num_connections fann_elliot fann_elliot_symmetric fann_errorfunc_linear fann_errorfunc_tanh fann_gaussian fann_gaussian_stepwise fann_gaussian_symmetric fann_get_activation_function fann_get_activation_steepness fann_get_bias_array fann_get_bit_fail fann_get_bit_fail_limit fann_get_cascade_activation_functions fann_get_cascade_activation_functions_count fann_get_cascade_activation_steepnesses fann_get_cascade_activation_steepnesses_count fann_get_cascade_candidate_change_fraction fann_get_cascade_candidate_limit fann_get_cascade_candidate_stagnation_epochs fann_get_cascade_max_cand_epochs fann_get_cascade_max_out_epochs fann_get_cascade_min_cand_epochs fann_get_cascade_min_out_epochs fann_get_cascade_num_candidate_groups fann_get_cascade_num_candidates fann_get_cascade_output_change_fraction fann_get_cascade_output_stagnation_epochs fann_get_cascade_weight_multiplier fann_get_connection_array fann_get_connection_rate fann_get_errno fann_get_errstr fann_get_layer_array fann_get_learning_momentum fann_get_learning_rate fann_get_mse fann_get_network_type fann_get_num_input fann_get_num_layers fann_get_num_output fann_get_quickprop_decay fann_get_quickprop_mu fann_get_rprop_decrease_factor fann_get_rprop_delta_max fann_get_rprop_delta_min fann_get_rprop_delta_zero fann_get_rprop_increase_factor fann_get_sarprop_step_error_shift fann_get_sarprop_step_error_threshold_factor fann_get_sarprop_temperature fann_get_sarprop_weight_decay_shift fann_get_total_connections fann_get_total_neurons fann_get_train_error_function fann_get_train_stop_function fann_get_training_algorithm fann_init_weights fann_length_train_data fann_linear fann_linear_piece fann_linear_piece_symmetric fann_merge_train_data fann_nettype_layer fann_nettype_shortcut fann_num_input_train_data fann_num_output_train_data fann_print_error fann_randomize_weights fann_read_train_from_file fann_reset_errno fann_reset_errstr fann_reset_mse fann_run fann_save fann_save_train fann_scale_input fann_scale_input_train_data fann_scale_output fann_scale_output_train_data fann_scale_train fann_scale_train_data fann_set_activation_function fann_set_activation_function_hidden fann_set_activation_function_layer fann_set_activation_function_output fann_set_activation_steepness fann_set_activation_steepness_hidden fann_set_activation_steepness_layer fann_set_activation_steepness_output fann_set_bit_fail_limit fann_set_callback fann_set_cascade_activation_functions fann_set_cascade_activation_steepnesses fann_set_cascade_candidate_change_fraction fann_set_cascade_candidate_limit fann_set_cascade_candidate_stagnation_epochs fann_set_cascade_max_cand_epochs fann_set_cascade_max_out_epochs fann_set_cascade_min_cand_epochs fann_set_cascade_min_out_epochs fann_set_cascade_num_candidate_groups fann_set_cascade_output_change_fraction fann_set_cascade_output_stagnation_epochs fann_set_cascade_weight_multiplier fann_set_error_log fann_set_input_scaling_params fann_set_learning_momentum fann_set_learning_rate fann_set_output_scaling_params fann_set_quickprop_decay fann_set_quickprop_mu fann_set_rprop_decrease_factor fann_set_rprop_delta_max fann_set_rprop_delta_min fann_set_rprop_delta_zero fann_set_rprop_increase_factor fann_set_sarprop_step_error_shift fann_set_sarprop_step_error_threshold_factor fann_set_sarprop_temperature fann_set_sarprop_weight_decay_shift fann_set_scaling_params fann_set_train_error_function fann_set_train_stop_function fann_set_training_algorithm fann_set_weight fann_set_weight_array fann_shuffle_train_data fann_sigmoid fann_sigmoid_stepwise fann_sigmoid_symmetric fann_sigmoid_symmetric_stepwise fann_sin fann_sin_symmetric fann_stopfunc_bit fann_stopfunc_mse fann_subset_train_data fann_test fann_test_data fann_threshold fann_threshold_symmetric fann_train fann_train_batch fann_train_epoch fann_train_incremental fann_train_on_data fann_train_on_file fann_train_quickprop fann_train_rprop fann_train_sarprop fastcgi_finish_request fbsql_affected_rows fbsql_assoc fbsql_autocommit fbsql_blob_size fbsql_both fbsql_change_user fbsql_clob_size fbsql_close fbsql_commit fbsql_connect fbsql_create_blob fbsql_create_clob fbsql_create_db fbsql_data_seek fbsql_database fbsql_database_password fbsql_db_query fbsql_db_status fbsql_drop_db fbsql_errno fbsql_error fbsql_fetch_array fbsql_fetch_assoc fbsql_fetch_field fbsql_fetch_lengths fbsql_fetch_object fbsql_fetch_row fbsql_field_flags fbsql_field_len fbsql_field_name fbsql_field_seek fbsql_field_table fbsql_field_type fbsql_free_result fbsql_get_autostart_info fbsql_hostname fbsql_insert_id fbsql_iso_read_committed fbsql_iso_read_uncommitted fbsql_iso_repeatable_read fbsql_iso_serializable fbsql_iso_versioned fbsql_list_dbs fbsql_list_fields fbsql_list_tables fbsql_lob_direct fbsql_lob_handle fbsql_lock_deferred fbsql_lock_optimistic fbsql_lock_pessimistic fbsql_next_result fbsql_noexec fbsql_num fbsql_num_fields fbsql_num_rows fbsql_password fbsql_pconnect fbsql_query fbsql_read_blob fbsql_read_clob fbsql_result fbsql_rollback fbsql_rows_fetched fbsql_running fbsql_select_db fbsql_set_characterset fbsql_set_lob_mode fbsql_set_password fbsql_set_transaction fbsql_start_db fbsql_starting fbsql_stop_db fbsql_stopped fbsql_stopping fbsql_table_name fbsql_tablename fbsql_unknown fbsql_username fbsql_warnings fclose fdf_add_doc_javascript fdf_add_template fdf_close fdf_create fdf_enum_values fdf_errno fdf_error fdf_get_ap fdf_get_attachment fdf_get_encoding fdf_get_file fdf_get_flags fdf_get_opt fdf_get_status fdf_get_value fdf_get_version fdf_header fdf_next_field_name fdf_open fdf_open_string fdf_remove_item fdf_save fdf_save_string fdf_set_ap fdf_set_encoding fdf_set_file fdf_set_flags fdf_set_javascript_action fdf_set_on_import_javascript fdf_set_opt fdf_set_status fdf_set_submit_form_action fdf_set_target_frame fdf_set_value fdf_set_version fdfaa fdfaction fdfap fdfapref fdfas fdfcalculate fdfclearff fdfclrf fdfdown fdfdownap fdfenter fdfexit fdfff fdffile fdfflags fdfformat fdfid fdfif fdfkeystroke fdfnormalap fdfrolloverap fdfsetf fdfsetff fdfstatus fdfup fdfvalidate fdfvalue feof fflush fgetc fgetcsv fgets fgetss file file_append file_binary file_exists file_get_contents file_ignore_new_lines file_no_default_context file_put_contents file_skip_empty_lines file_text file_use_include_path fileatime filectime filegroup fileinfo_continue fileinfo_devices fileinfo_mime fileinfo_mime_encoding fileinfo_mime_type fileinfo_none fileinfo_preserve_atime fileinfo_raw fileinfo_symlink fileinode filemtime fileowner fileperms filepro filepro_fieldcount filepro_fieldname filepro_fieldtype filepro_fieldwidth filepro_retrieve filepro_rowcount filesize filetype filter_callback filter_default filter_flag_allow_fraction filter_flag_allow_hex filter_flag_allow_octal filter_flag_allow_scientific filter_flag_allow_thousand filter_flag_empty_string_null filter_flag_encode_amp filter_flag_encode_high filter_flag_encode_low filter_flag_host_required filter_flag_ipv4 filter_flag_ipv6 filter_flag_no_encode_quotes filter_flag_no_priv_range filter_flag_no_res_range filter_flag_none filter_flag_path_required filter_flag_query_required filter_flag_scheme_required filter_flag_strip_backtick filter_flag_strip_high filter_flag_strip_low filter_force_array filter_has_var filter_id filter_input filter_input_array filter_list filter_null_on_failure filter_require_array filter_require_scalar filter_sanitize_email filter_sanitize_encoded filter_sanitize_full_special_chars filter_sanitize_magic_quotes filter_sanitize_number_float filter_sanitize_number_int filter_sanitize_special_chars filter_sanitize_string filter_sanitize_stripped filter_sanitize_url filter_unsafe_raw filter_validate_boolean filter_validate_email filter_validate_float filter_validate_int filter_validate_ip filter_validate_mac filter_validate_regexp filter_validate_url filter_var filter_var_array final finally finfo_buffer finfo_close finfo_file finfo_open finfo_set_flags firebird/interbase float floatval flock floor flush fmod fnm_casefold fnm_noescape fnm_pathname fnm_period fnmatch fopen for force_deflate force_gzip foreach forward_static_call forward_static_call_array fpassthru fpe_fltdiv fpe_fltinv fpe_fltovf fpe_fltres fpe_fltsub fpe_fltund fpe_intdiv fpe_intovf fprintf fputcsv fputs frac_digits fread frenchtojd fscanf fseek fsockopen fstat ft_internal ft_not ft_peek ft_prefetchtext ft_uid ftell ftok ftp_alloc ftp_ascii ftp_autoresume ftp_autoseek ftp_binary ftp_cdup ftp_chdir ftp_chmod ftp_close ftp_connect ftp_delete ftp_exec ftp_failed ftp_fget ftp_finished ftp_fput ftp_get ftp_get_option ftp_image ftp_login ftp_mdtm ftp_mkdir ftp_moredata ftp_nb_continue ftp_nb_fget ftp_nb_fput ftp_nb_get ftp_nb_put ftp_nlist ftp_pasv ftp_put ftp_pwd ftp_quit ftp_raw ftp_rawlist ftp_rename ftp_rmdir ftp_set_option ftp_site ftp_size ftp_ssl_connect ftp_systype ftp_text ftp_timeout_sec ftruncate func_get_arg func_get_args func_num_args function function_exists function_trace fwrite gc_collect_cycles gc_disable gc_enable gc_enabled gd_bundled gd_extra_version gd_info gd_major_version gc_mem_caches gd_minor_version gd_release_version gd_version geoip_asnum_by_name geoip_asnum_edition geoip_cabledsl_speed geoip_city_edition_rev0 geoip_city_edition_rev1 geoip_continent_code_by_name geoip_corporate_speed geoip_country_code3_by_name geoip_country_code_by_name geoip_country_edition geoip_country_name_by_name geoip_database_info geoip_db_avail geoip_db_filename geoip_db_get_all_info geoip_dialup_speed geoip_domain_by_name geoip_domain_edition geoip_id_by_name geoip_isp_by_name geoip_isp_edition geoip_netspeed_edition geoip_netspeedcell_by_name geoip_org_by_name geoip_org_edition geoip_proxy_edition geoip_record_by_name geoip_region_by_name geoip_region_edition_rev0 geoip_region_edition_rev1 geoip_region_name_by_code geoip_setup_custom_directory geoip_time_zone_by_country_and_region geoip_unknown_speed get_browser get_called_class get_cfg_var get_class get_class_methods get_class_vars get_current_user get_declared_classes get_declared_interfaces get_declared_traits get_defined_constants get_defined_functions get_defined_vars get_extension_funcs get_headers get_html_translation_table get_include_path get_included_files get_loaded_extensions get_magic_quotes_gpc get_magic_quotes_runtime get_meta_tags get_object_vars get_parent_class get_required_files get_resource_type get_resources getallheaders getcwd getdate getdir getenv gethostbyaddr gethostbyname gethostbynamel gethostname getimagesize getimagesizefromstring getlastmod getmxrr getmygid getmyinode getmypid getmyuid getopt getprotobyname getprotobynumber getrandmax getrusage getservbyname getservbyport gettext gettimeofday gettype glob glob_available_flags glob_brace glob_err glob_mark glob_nocheck glob_noescape glob_nosort glob_onlydir global globals gmdate gmmktime gmp_abs gmp_add gmp_and gmp_big_endian gmp_clrbit gmp_cmp gmp_com gmp_div gmp_div_q gmp_div_qr gmp_div_r gmp_divexact gmp_export gmp_fact gmp_gcd gmp_gcdext gmp_hamdist gmp_import gmp_init gmp_intval gmp_invert gmp_jacobi gmp_legendre gmp_little_endian gmp_lsw_first gmp_mod gmp_mpir_version gmp_msw_first gmp_mul gmp_native_endian gmp_neg gmp_nextprime gmp_or gmp_perfect_square gmp_popcount gmp_pow gmp_powm gmp_prob_prime gmp_random gmp_random_bits gmp_random_range gmp_random_seed gmp_root gmp_rootrem gmp_round_minusinf gmp_round_plusinf gmp_round_zero gmp_scan0 gmp_scan1 gmp_setbit gmp_sign gmp_sqrt gmp_sqrtrem gmp_strval gmp_sub gmp_testbit gmp_version gmp_xor gmstrftime gnupg_adddecryptkey gnupg_addencryptkey gnupg_addsignkey gnupg_cleardecryptkeys gnupg_clearencryptkeys gnupg_clearsignkeys gnupg_decrypt gnupg_decryptverify gnupg_encrypt gnupg_encryptsign gnupg_error_exception gnupg_error_silent gnupg_error_warning gnupg_export gnupg_geterror gnupg_getprotocol gnupg_import gnupg_init gnupg_keyinfo gnupg_protocol_cms gnupg_protocol_openpgp gnupg_setarmor gnupg_seterrormode gnupg_setsignmode gnupg_sig_mode_clear gnupg_sig_mode_detach gnupg_sig_mode_normal gnupg_sign gnupg_sigsum_bad_policy gnupg_sigsum_crl_missing gnupg_sigsum_crl_too_old gnupg_sigsum_green gnupg_sigsum_key_expired gnupg_sigsum_key_missing gnupg_sigsum_key_revoked gnupg_sigsum_red gnupg_sigsum_sig_expired gnupg_sigsum_sys_error gnupg_sigsum_valid gnupg_validity_full gnupg_validity_marginal gnupg_validity_never gnupg_validity_ultimate gnupg_validity_undefined gnupg_validity_unknown gnupg_verify gopher_binary gopher_binhex gopher_directory gopher_document gopher_dosbinary gopher_http gopher_info gopher_parsedir gopher_unknown gopher_uuencoded goto grapheme_extr_count grapheme_extr_maxbytes grapheme_extr_maxchars grapheme_extract grapheme_stripos grapheme_stristr grapheme_strlen grapheme_strpos grapheme_strripos grapheme_strrpos grapheme_strstr grapheme_substr gregoriantojd grouping gupnp_context_get_host_ip gupnp_context_get_port gupnp_context_get_subscription_timeout gupnp_context_host_path gupnp_context_new gupnp_context_set_subscription_timeout gupnp_context_timeout_add gupnp_context_unhost_path gupnp_control_error_action_failed gupnp_control_error_invalid_action gupnp_control_error_invalid_args gupnp_control_error_out_of_sync gupnp_control_point_browse_start gupnp_control_point_browse_stop gupnp_control_point_callback_set gupnp_control_point_new gupnp_device_action_callback_set gupnp_device_info_get gupnp_device_info_get_service gupnp_root_device_get_available gupnp_root_device_get_relative_location gupnp_root_device_new gupnp_root_device_set_available gupnp_root_device_start gupnp_root_device_stop gupnp_service_action_get gupnp_service_action_return gupnp_service_action_return_error gupnp_service_action_set gupnp_service_freeze_notify gupnp_service_info_get gupnp_service_info_get_introspection gupnp_service_introspection_get_state_variable gupnp_service_notify gupnp_service_proxy_action_get gupnp_service_proxy_action_set gupnp_service_proxy_add_notify gupnp_service_proxy_callback_set gupnp_service_proxy_get_subscribed gupnp_service_proxy_remove_notify gupnp_service_proxy_send_action gupnp_service_proxy_set_subscribed gupnp_service_thaw_notify gupnp_signal_action_invoked gupnp_signal_device_proxy_available gupnp_signal_device_proxy_unavailable gupnp_signal_notify_failed gupnp_signal_service_proxy_available gupnp_signal_service_proxy_unavailable gupnp_signal_subscription_lost gupnp_type_boolean gupnp_type_double gupnp_type_float gupnp_type_int gupnp_type_long gupnp_type_string gzclose gzcompress gzdecode gzdeflate gzencode gzeof gzfile gzgetc gzgets gzgetss gzinflate gzopen gzpassthru gzputs gzread gzrewind gzseek gztell gzuncompress gzwrite hash hash_algos hash_copy hash_equals hash_file hash_final hash_hmac hash_hmac_file hash_init hash_pbkdf2 hash_update hash_update_file hash_update_stream header header_register_callback header_remove headers_list headers_sent hebrev hebrevc hex2bin hexdec highlight_file highlight_string html_entities html_entity_decode html_specialchars htmlentities htmlspecialchars htmlspecialchars_decode http_auth_any http_auth_basic http_auth_digest http_auth_gssneg http_auth_ntlm http_build_cookie http_build_query http_build_str http_build_url http_cache_etag http_cache_last_modified http_chunked_decode http_cookie_httponly http_cookie_parse_raw http_cookie_secure http_date http_deflate http_deflate_level_def http_deflate_level_max http_deflate_level_min http_deflate_strategy_def http_deflate_strategy_filt http_deflate_strategy_fixed http_deflate_strategy_huff http_deflate_strategy_rle http_deflate_type_gzip http_deflate_type_raw http_deflate_type_zlib http_e_encoding http_e_header http_e_invalid_param http_e_malformed_headers http_e_message_type http_e_querystring http_e_request http_e_request_method http_e_request_pool http_e_response http_e_runtime http_e_socket http_e_url http_encoding_stream_flush_full http_encoding_stream_flush_none http_encoding_stream_flush_sync http_get http_get_request_body http_get_request_body_stream http_get_request_headers http_head http_inflate http_ipresolve_any http_ipresolve_v4 http_ipresolve_v6 http_match_etag http_match_modified http_match_request_header http_meth_acl http_meth_baseline_control http_meth_checkin http_meth_checkout http_meth_connect http_meth_copy http_meth_delete http_meth_get http_meth_head http_meth_label http_meth_lock http_meth_merge http_meth_mkactivity http_meth_mkcol http_meth_mkworkspace http_meth_move http_meth_options http_meth_post http_meth_propfind http_meth_proppatch http_meth_put http_meth_report http_meth_trace http_meth_uncheckout http_meth_unlock http_meth_update http_meth_version_control http_msg_none http_msg_request http_msg_response http_negotiate_charset http_negotiate_content_type http_negotiate_language http_params_allow_comma http_params_allow_failure http_params_default http_params_raise_error http_parse_cookie http_parse_headers http_parse_message http_parse_params http_persistent_handles_clean http_persistent_handles_count http_persistent_handles_ident http_post_data http_post_fields http_proxy_http http_proxy_socks4 http_proxy_socks5 http_put_data http_put_file http_put_stream http_querystring_type_array http_querystring_type_bool http_querystring_type_float http_querystring_type_int http_querystring_type_object http_querystring_type_string http_redirect http_redirect_found http_redirect_perm http_redirect_post http_redirect_proxy http_redirect_temp http_request http_request_body_encode http_request_method_exists http_request_method_name http_request_method_register http_request_method_unregister http_response_code http_send_content_disposition http_send_content_type http_send_data http_send_file http_send_last_modified http_send_status http_send_stream http_ssl_version_any http_ssl_version_sslv2 http_ssl_version_sslv3 http_ssl_version_tlsv1 http_support http_support_encodings http_support_magicmime http_support_requests http_support_sslrequests http_throttle http_url_join_path http_url_join_query http_url_replace http_url_strip_all http_url_strip_auth http_url_strip_fragment http_url_strip_pass http_url_strip_path http_url_strip_port http_url_strip_query http_url_strip_user http_version_1_0 http_version_1_1 http_version_any hypot ibase_add_user ibase_affected_rows ibase_backup ibase_bkp_convert ibase_bkp_ignore_checksums ibase_bkp_ignore_limbo ibase_bkp_metadata_only ibase_bkp_no_garbage_collect ibase_bkp_non_transportable ibase_bkp_old_descriptions ibase_blob_add ibase_blob_cancel ibase_blob_close ibase_blob_create ibase_blob_echo ibase_blob_get ibase_blob_import ibase_blob_info ibase_blob_open ibase_close ibase_commit ibase_commit_ret ibase_committed ibase_concurrency ibase_connect ibase_consistency ibase_db_info ibase_default ibase_delete_user ibase_drop_db ibase_errcode ibase_errmsg ibase_execute ibase_fetch_arrays ibase_fetch_assoc ibase_fetch_blobs ibase_fetch_object ibase_fetch_row ibase_field_info ibase_free_event_handler ibase_free_query ibase_free_result ibase_gen_id ibase_maintain_db ibase_modify_user ibase_name_result ibase_nowait ibase_num_fields ibase_num_params ibase_param_info ibase_pconnect ibase_prepare ibase_prp_access_mode ibase_prp_activate ibase_prp_am_readonly ibase_prp_am_readwrite ibase_prp_db_online ibase_prp_deny_new_attachments ibase_prp_deny_new_transactions ibase_prp_page_buffers ibase_prp_res ibase_prp_res_use_full ibase_prp_reserve_space ibase_prp_set_sql_dialect ibase_prp_shutdown_db ibase_prp_sweep_interval ibase_prp_wm_async ibase_prp_wm_sync ibase_prp_write_mode ibase_query ibase_read ibase_res_create ibase_res_deactivate_idx ibase_res_no_shadow ibase_res_no_validity ibase_res_one_at_a_time ibase_res_replace ibase_res_use_all_space ibase_restore ibase_rollback ibase_rollback_ret ibase_rpr_check_db ibase_rpr_full ibase_rpr_ignore_checksum ibase_rpr_kill_shadows ibase_rpr_mend_db ibase_rpr_sweep_db ibase_rpr_validate_db ibase_server_info ibase_service_attach ibase_service_detach ibase_set_event_handler ibase_sts_data_pages ibase_sts_db_log ibase_sts_hdr_pages ibase_sts_idx_pages ibase_sts_sys_relations ibase_svc_get_env ibase_svc_get_env_lock ibase_svc_get_env_msg ibase_svc_get_users ibase_svc_implementation ibase_svc_server_version ibase_svc_svr_db_info ibase_svc_user_dbpath ibase_trans ibase_unixtime ibase_wait ibase_wait_event ibase_write iconv iconv_get_encoding iconv_impl iconv_mime_decode iconv_mime_decode_continue_on_error iconv_mime_decode_headers iconv_mime_decode_strict iconv_mime_encode iconv_set_encoding iconv_strlen iconv_strpos iconv_strrpos iconv_substr iconv_version id3_best id3_get_frame_long_name id3_get_frame_short_name id3_get_genre_id id3_get_genre_list id3_get_genre_name id3_get_tag id3_get_version id3_remove_tag id3_set_tag id3_v1_0 id3_v1_1 id3_v2_1 id3_v2_2 id3_v2_3 id3_v2_4 idate idn_to_ascii idn_to_unicode idn_to_utf8 idna_allow_unassigned idna_check_bidi idna_check_contextj idna_default idna_error_bidi idna_error_contextj idna_error_disallowed idna_error_domain_name_too_long idna_error_empty_label idna_error_hyphen_3_4 idna_error_invalid_ace_label idna_error_label_has_dot idna_error_label_too_long idna_error_leading_combining_mark idna_error_leading_hyphen idna_error_punycode idna_error_trailing_hyphen idna_nontransitional_to_ascii idna_nontransitional_to_unicode idna_use_std3_rules if ifx_affected_rows ifx_blobinfile_mode ifx_byteasvarchar ifx_close ifx_connect ifx_copy_blob ifx_create_blob ifx_create_char ifx_do ifx_error ifx_errormsg ifx_fetch_row ifx_fieldproperties ifx_fieldtypes ifx_free_blob ifx_free_char ifx_free_result ifx_get_blob ifx_get_char ifx_getsqlca ifx_hold ifx_htmltbl_result ifx_lo_append ifx_lo_buffer ifx_lo_nobuffer ifx_lo_rdonly ifx_lo_rdwr ifx_lo_wronly ifx_nullformat ifx_num_fields ifx_num_rows ifx_pconnect ifx_prepare ifx_query ifx_scroll ifx_textasvarchar ifx_update_blob ifx_update_char ifxus_close_slob ifxus_create_slob ifxus_free_slob ifxus_open_slob ifxus_read_slob ifxus_seek_slob ifxus_tell_slob ifxus_write_slob ignore_user_abort iis_add_server iis_anonymous iis_basic iis_execute iis_get_dir_security iis_get_script_map iis_get_server_by_comment iis_get_server_by_path iis_get_server_rights iis_get_service_state iis_ntlm iis_paused iis_read iis_remove_server iis_running iis_script iis_set_app_settings iis_set_dir_security iis_set_script_map iis_set_server_rights iis_start_server iis_start_service iis_starting iis_stop_server iis_stop_service iis_stopped iis_write ill_badstk ill_coproc ill_illadr ill_illopc ill_illopn ill_illtrp ill_prvopc ill_prvreg image2wbmp image_type_to_extension image_type_to_mime_type imageaffine imageaffinematrixconcat imageaffinematrixget imagealphablending imageantialias imagearc imagechar imagecharup imagecolorallocate imagecolorallocatealpha imagecolorat imagecolorclosest imagecolorclosestalpha imagecolorclosesthwb imagecolordeallocate imagecolorexact imagecolorexactalpha imagecolormatch imagecolorresolve imagecolorresolvealpha imagecolorset imagecolorsforindex imagecolorstotal imagecolortransparent imageconvolution imagecopy imagecopymerge imagecopymergegray imagecopyresampled imagecopyresized imagecreate imagecreatefromgd imagecreatefromgd2 imagecreatefromgd2part imagecreatefromgif imagecreatefromjpeg imagecreatefrompng imagecreatefromstring imagecreatefromwbmp imagecreatefromwebp imagecreatefromxbm imagecreatefromxpm imagecreatetruecolor imagecrop imagecropauto imagedashedline imagedestroy imageellipse imagefill imagefilledarc imagefilledellipse imagefilledpolygon imagefilledrectangle imagefilltoborder imagefilter imageflip imagefontheight imagefontwidth imageftbbox imagefttext imagegammacorrect imagegd imagegd2 imagegif imagegrabscreen imagegrabwindow imageinterlace imageistruecolor imagejpeg imagelayereffect imageline imageloadfont imagepalettecopy imagepalettetotruecolor imagepng imagepolygon imagepsbbox imagepsencodefont imagepsextendfont imagepsfreefont imagepsloadfont imagepsslantfont imagepstext imagerectangle imagerotate imagesavealpha imagescale imagesetbrush imagesetinterpolation imagesetpixel imagesetstyle imagesetthickness imagesettile imagestring imagestringup imagesx imagesy imagetruecolortopalette imagettfbbox imagettftext imagetype_bmp imagetype_count imagetype_gif imagetype_ico imagetype_iff imagetype_jb2 imagetype_jp2 imagetype_jpc imagetype_jpeg imagetype_jpeg2000 imagetype_jpx imagetype_png imagetype_psd imagetype_swc imagetype_swf imagetype_tiff_ii imagetype_tiff_mm imagetype_unknown imagetype_wbmp imagetype_xbm imagetypes imagewbmp imagewebp imagexbm imap_8bit imap_alerts imap_append imap_base64 imap_binary imap_body imap_bodystruct imap_check imap_clearflag_full imap_close imap_closetimeout imap_create imap_createmailbox imap_delete imap_deletemailbox imap_errors imap_expunge imap_fetch_overview imap_fetchbody imap_fetchheader imap_fetchmime imap_fetchstructure imap_fetchtext imap_gc imap_gc_elt imap_gc_env imap_gc_texts imap_get_quota imap_get_quotaroot imap_getacl imap_getmailboxes imap_getsubscribed imap_header imap_headerinfo imap_headers imap_last_error imap_list imap_listmailbox imap_listscan imap_listsubscribed imap_lsub imap_mail imap_mail_compose imap_mail_copy imap_mail_move imap_mailboxmsginfo imap_mime_header_decode imap_msgno imap_mutf7_to_utf8 imap_num_msg imap_num_recent imap_open imap_opentimeout imap_ping imap_qprint imap_readtimeout imap_rename imap_renamemailbox imap_reopen imap_rfc822_parse_adrlist imap_rfc822_parse_headers imap_rfc822_write_address imap_savebody imap_scan imap_scanmailbox imap_search imap_set_quota imap_setacl imap_setflag_full imap_sort imap_status imap_subscribe imap_thread imap_timeout imap_uid imap_undelete imap_unsubscribe imap_utf7_decode imap_utf7_encode imap_utf8 imap_utf8_to_mutf7 imap_writetimeout img_affine_rotate img_affine_scale img_affine_shear_horizontal img_affine_shear_vertical img_affine_translate img_arc_chord img_arc_edged img_arc_nofill img_arc_pie img_arc_rounded img_bell img_bessel img_bicubic img_bicubic_fixed img_bilinear_fixed img_blackman img_box img_bspline img_catmullrom img_color_brushed img_color_styled img_color_styledbrushed img_color_tiled img_color_transparent img_crop_black img_crop_default img_crop_sides img_crop_threshold img_crop_transparent img_crop_white img_effect_alphablend img_effect_normal img_effect_overlay img_effect_replace img_filter_brightness img_filter_colorize img_filter_contrast img_filter_edgedetect img_filter_emboss img_filter_gaussian_blur img_filter_grayscale img_filter_mean_removal img_filter_negate img_filter_pixelate img_filter_selective_blur img_filter_smooth img_flip_both img_flip_horizontal img_flip_vertical img_gaussian img_gd2_compressed img_gd2_raw img_generalized_cubic img_gif img_hamming img_hanning img_hermite img_jpeg img_jpg img_mitchell img_nearest_neighbour img_png img_power img_quadratic img_sinc img_triangle img_wbmp img_weighted4 img_xpm implements implode import_request_variables in_access in_all_events in_array in_attrib in_close in_close_nowrite in_close_write in_create in_delete in_delete_self in_dont_follow in_ignored in_isdir in_mask_add in_modify in_move in_move_self in_moved_from in_moved_to in_oneshot in_onlydir in_open in_q_overflow in_unmount include include_once inet_ntop inet_pton inf info_all info_configuration info_credits info_environment info_general info_license info_modules info_variables ingres_api_version ingres_assoc ingres_autocommit ingres_autocommit_state ingres_both ingres_charset ingres_close ingres_commit ingres_connect ingres_cursor ingres_cursor_readonly ingres_cursor_update ingres_date_dmy ingres_date_finnish ingres_date_german ingres_date_iso ingres_date_iso4 ingres_date_mdy ingres_date_multinational ingres_date_multinational4 ingres_date_ymd ingres_errno ingres_error ingres_errsqlstate ingres_escape_string ingres_execute ingres_ext_version ingres_fetch_array ingres_fetch_assoc ingres_fetch_object ingres_fetch_proc_return ingres_fetch_row ingres_field_length ingres_field_name ingres_field_nullable ingres_field_precision ingres_field_scale ingres_field_type ingres_free_result ingres_money_leading ingres_money_trailing ingres_next_error ingres_num ingres_num_fields ingres_num_rows ingres_pconnect ingres_prepare ingres_query ingres_result_seek ingres_rollback ingres_set_environment ingres_structure_btree ingres_structure_cbtree ingres_structure_chash ingres_structure_cheap ingres_structure_cisam ingres_structure_hash ingres_structure_heap ingres_structure_isam ingres_unbuffered_query ini_all ini_alter ini_get ini_get_all ini_perdir ini_restore ini_scanner_normal ini_scanner_raw ini_scanner_typed ini_set ini_system ini_user inotify_add_watch inotify_init inotify_queue_len inotify_read inotify_rm_watch input_cookie input_env input_get input_post input_request input_server input_session instanceof insteadof int int_curr_symbol int_frac_digits intdiv integer interface interface_exists intl_error_name intl_get_error_code intl_get_error_message intl_icu_data_version intl_icu_version intl_idna_variant_2003 intl_idna_variant_uts46 intl_is_failure intl_max_locale_len intval ion_clock_skew ion_corrupt_file ion_expired_file ion_license_corrupt ion_license_expired ion_license_header_invalid ion_license_not_found ion_license_property_invalid ion_license_server_invalid ion_no_permissions ion_unauth_append_prepend_file ion_unauth_included_file ion_unauth_including_file ion_untrusted_extension ioncube_check_license_properties ioncube_file_info ioncube_file_is_encoded ioncube_file_not_permissioned ioncube_file_properties ioncube_license_has_expired ioncube_license_matches_server ioncube_license_properties ioncube_licensed_servers ioncube_loader_iversion ioncube_loader_version ioncube_read_file ioncube_server_data ioncube_write_file ip2long ip_multicast_if ip_multicast_loop ip_multicast_ttl ipproto_ip ipproto_ipv6 iptcembed iptcparse ipv6_hoplimit ipv6_multicast_hops ipv6_multicast_if ipv6_multicast_loop ipv6_pktinfo ipv6_recvhoplimit ipv6_recvpktinfo ipv6_recvtclass ipv6_tclass ipv6_unicast_hops is_a is_array is_bool is_callable is_dir is_double is_executable is_file is_finite is_float is_infinite is_int is_integer is_link is_long is_nan is_null is_numeric is_object is_readable is_real is_resource is_scalar is_soap_fault is_string is_subclass_of is_tainted is_uploaded_file is_writable is_writeable isset iterator_apply iterator_count iterator_to_array jddayofweek jdmonthname jdtofrench jdtogregorian jdtojewish jdtojulian jdtounix jewishtojd join jpeg2wbmp json_bigint_as_string json_decode json_encode json_error_ctrl_char json_error_depth json_error_inf_or_nan json_error_none json_error_recursion json_error_state_mismatch json_error_syntax json_error_unsupported_type json_error_utf8 json_force_object json_hex_amp json_hex_apos json_hex_quot json_hex_tag json_last_error json_last_error_msg json_numeric_check json_object_as_array json_partial_output_on_error json_preserve_zero_fraction json_pretty_print json_unescaped_slashes json_unescaped_unicode judy_type judy_version juliantojd kadm5_attributes kadm5_chpass_principal kadm5_clearpolicy kadm5_create_principal kadm5_delete_principal kadm5_destroy kadm5_fail_auth_count kadm5_flush kadm5_get_policies kadm5_get_principal kadm5_get_principals kadm5_init_with_password kadm5_kvno kadm5_last_failed kadm5_last_pw_change kadm5_last_success kadm5_max_life kadm5_max_rlife kadm5_mod_name kadm5_mod_time kadm5_modify_principal kadm5_policy kadm5_princ_expire_time kadm5_principal kadm5_pw_expiration kadm5_randkey key key_exists krb5_kdb_disallow_all_tix krb5_kdb_disallow_dup_skey krb5_kdb_disallow_forwardable krb5_kdb_disallow_postdated krb5_kdb_disallow_proxiable krb5_kdb_disallow_renewable krb5_kdb_disallow_svr krb5_kdb_disallow_tgt_based krb5_kdb_new_princ krb5_kdb_pwchange_server krb5_kdb_requires_hw_auth krb5_kdb_requires_pre_auth krb5_kdb_requires_pwchange krb5_kdb_support_desmd5 krsort ksort latt_haschildren latt_hasnochildren latt_marked latt_noinferiors latt_noselect latt_referral latt_unmarked lc_all lc_collate lc_ctype lc_messages lc_monetary lc_numeric lc_time lcfirst lcg_value lchgrp lchown ldap_8859_to_t61 ldap_add ldap_bind ldap_close ldap_compare ldap_connect ldap_control_paged_result ldap_control_paged_result_response ldap_count_entries ldap_delete ldap_dn2ufn ldap_err2str ldap_errno ldap_error ldap_escape ldap_explode_dn ldap_first_attribute ldap_first_entry ldap_first_reference ldap_free_result ldap_get_attributes ldap_get_dn ldap_get_entries ldap_get_option ldap_get_values ldap_get_values_len ldap_list ldap_mod_add ldap_mod_del ldap_mod_replace ldap_modify ldap_modify_batch ldap_next_attribute ldap_next_entry ldap_next_reference ldap_parse_reference ldap_parse_result ldap_read ldap_rename ldap_sasl_bind ldap_search ldap_set_option ldap_set_rebind_proc ldap_sort ldap_start_tls ldap_t61_to_8859 ldap_unbind levenshtein libexslt_dotted_version libexslt_version libxml_clear_errors libxml_compact libxml_disable_entity_loader libxml_dotted_version libxml_dtdattr libxml_dtdload libxml_dtdvalid libxml_err_error libxml_err_fatal libxml_err_none libxml_err_warning libxml_get_errors libxml_get_last_error libxml_html_nodefdtd libxml_html_noimplied libxml_loaded_version libxml_noblanks libxml_nocdata libxml_noemptytag libxml_noent libxml_noerror libxml_nonet libxml_nowarning libxml_noxmldecl libxml_nsclean libxml_parsehuge libxml_pedantic libxml_schema_create libxml_set_external_entity_loader libxml_set_streams_context libxml_use_internal_errors libxml_version libxml_xinclude libxslt_dotted_version libxslt_version link linkinfo list locale_accept_from_http locale_canonicalize locale_compose locale_filter_matches locale_get_all_variants locale_get_default locale_get_display_language locale_get_display_name locale_get_display_region locale_get_display_script locale_get_display_variant locale_get_keywords locale_get_primary_language locale_get_region locale_get_script locale_lookup locale_parse locale_set_default localeconv localtime lock_ex lock_nb lock_sh lock_un log log10 log1p log_alert log_auth log_authpriv log_cons log_crit log_cron log_daemon log_debug log_emerg log_err log_info log_kern log_local0 log_local1 log_local2 log_local3 log_local4 log_local5 log_local6 log_local7 log_lpr log_mail log_ndelay log_news log_notice log_nowait log_odelay log_perror log_pid log_syslog log_user log_uucp log_warning long2ip lstat ltrim lzf_compress lzf_decompress lzf_optimized_for m_1_pi m_2_pi m_2_sqrtpi m_checkstatus m_completeauthorizations m_connect m_connectionerror m_deletetrans m_destroyconn m_destroyengine m_done m_e m_error m_euler m_fail m_getcell m_getcellbynum m_getcommadelimited m_getheader m_initconn m_initengine m_iscommadelimited m_ln10 m_ln2 m_lnpi m_log10e m_log2e m_maxconntimeout m_monitor m_numcolumns m_numrows m_parsecommadelimited m_pending m_pi m_pi_2 m_pi_4 m_responsekeys m_responseparam m_returnstatus m_setblocking m_setdropfile m_setip m_setssl m_setssl_cafile m_setssl_files m_settimeout m_sqrt1_2 m_sqrt2 m_sqrt3 m_sqrtpi m_sslcert_gen_hash m_success m_transactionssent m_transinqueue m_transkeyval m_transnew m_transsend m_uwait m_validateidentifier m_verifyconnection m_verifysslcert magic_quotes_runtime mail mailparse_determine_best_xfer_encoding mailparse_extract_output mailparse_extract_return mailparse_extract_stream mailparse_msg_create mailparse_msg_extract_part mailparse_msg_extract_part_file mailparse_msg_extract_whole_part_file mailparse_msg_free mailparse_msg_get_part mailparse_msg_get_part_data mailparse_msg_get_structure mailparse_msg_parse mailparse_msg_parse_file mailparse_rfc822_parse_addresses mailparse_stream_encode mailparse_uudecode_all main max maxdb_affected_rows maxdb_application maxdb_appversion maxdb_assoc maxdb_assoc_lower maxdb_assoc_upper maxdb_autocommit maxdb_bind_param maxdb_bind_result maxdb_both maxdb_change_user maxdb_character_set_name maxdb_client_encoding maxdb_close maxdb_close_long_data maxdb_commit maxdb_compname maxdb_connect maxdb_connect_errno maxdb_connect_error maxdb_cursorprefix maxdb_data_seek maxdb_debug maxdb_disable_reads_from_master maxdb_disable_rpl_parse maxdb_dump_debug_info maxdb_embedded_connect maxdb_enable_reads_from_master maxdb_enable_rpl_parse maxdb_errno maxdb_error maxdb_escape_string maxdb_execute maxdb_fetch maxdb_fetch_array maxdb_fetch_assoc maxdb_fetch_field maxdb_fetch_field_direct maxdb_fetch_fields maxdb_fetch_lengths maxdb_fetch_object maxdb_fetch_row maxdb_field_count maxdb_field_seek maxdb_field_tell maxdb_free_result maxdb_get_client_info maxdb_get_client_version maxdb_get_host_info maxdb_get_metadata maxdb_get_proto_info maxdb_get_server_info maxdb_get_server_version maxdb_info maxdb_init maxdb_insert_id maxdb_isolationlevel maxdb_kill maxdb_master_query maxdb_more_results maxdb_multi_query maxdb_next_result maxdb_num maxdb_num_fields maxdb_num_rows maxdb_options maxdb_packetcount maxdb_param_count maxdb_ping maxdb_prepare maxdb_query maxdb_real_connect maxdb_real_escape_string maxdb_real_query maxdb_report maxdb_rollback maxdb_rpl_parse_enabled maxdb_rpl_probe maxdb_rpl_query_type maxdb_select_db maxdb_send_long_data maxdb_send_query maxdb_server_end maxdb_server_init maxdb_set_opt maxdb_sqlmode maxdb_sqlstate maxdb_ssl_set maxdb_stat maxdb_statementcachesize maxdb_stmt_affected_rows maxdb_stmt_bind_param maxdb_stmt_bind_result maxdb_stmt_close maxdb_stmt_close_long_data maxdb_stmt_data_seek maxdb_stmt_errno maxdb_stmt_error maxdb_stmt_execute maxdb_stmt_fetch maxdb_stmt_free_result maxdb_stmt_init maxdb_stmt_num_rows maxdb_stmt_param_count maxdb_stmt_prepare maxdb_stmt_reset maxdb_stmt_result_metadata maxdb_stmt_send_long_data maxdb_stmt_sqlstate maxdb_stmt_store_result maxdb_store_result maxdb_thread_id maxdb_thread_safe maxdb_timeout maxdb_unicode maxdb_use_result maxdb_warning_count mb_case_lower mb_case_title mb_case_upper mb_check_encoding mb_convert_case mb_convert_encoding mb_convert_kana mb_convert_variables mb_decode_mimeheader mb_decode_numericentity mb_detect_encoding mb_detect_order mb_encode_mimeheader mb_encode_numericentity mb_encoding_aliases mb_ereg mb_ereg_match mb_ereg_replace mb_ereg_replace_callback mb_ereg_search mb_ereg_search_getpos mb_ereg_search_getregs mb_ereg_search_init mb_ereg_search_pos mb_ereg_search_regs mb_ereg_search_setpos mb_eregi mb_eregi_replace mb_get_info mb_http_input mb_http_output mb_internal_encoding mb_language mb_list_encodings mb_output_handler mb_overload_mail mb_overload_regex mb_overload_string mb_parse_str mb_preferred_mime_name mb_regex_encoding mb_regex_set_options mb_send_mail mb_split mb_strcut mb_strimwidth mb_stripos mb_stristr mb_strlen mb_strpos mb_strrchr mb_strrichr mb_strripos mb_strrpos mb_strstr mb_strtolower mb_strtoupper mb_strwidth mb_substitute_character mb_substr mb_substr_count mbereg mbereg_match mbereg_replace mbereg_search mbereg_search_getpos mbereg_search_getregs mbereg_search_init mbereg_search_pos mbereg_search_regs mbereg_search_setpos mberegi mberegi_replace mbregex_encoding mbsplit mcast_block_source mcast_join_group mcast_join_source_group mcast_leave_group mcast_leave_source_group mcast_unblock_source mcrypt_3des mcrypt_arcfour mcrypt_arcfour_iv mcrypt_blowfish mcrypt_blowfish_compat mcrypt_cast_128 mcrypt_cast_256 mcrypt_cbc mcrypt_cfb mcrypt_create_iv mcrypt_crypt mcrypt_decrypt mcrypt_des mcrypt_dev_random mcrypt_dev_urandom mcrypt_ecb mcrypt_enc_get_algorithms_name mcrypt_enc_get_block_size mcrypt_enc_get_iv_size mcrypt_enc_get_key_size mcrypt_enc_get_modes_name mcrypt_enc_get_supported_key_sizes mcrypt_enc_is_block_algorithm mcrypt_enc_is_block_algorithm_mode mcrypt_enc_is_block_mode mcrypt_enc_self_test mcrypt_encrypt mcrypt_enigna mcrypt_generic mcrypt_generic_deinit mcrypt_generic_end mcrypt_generic_init mcrypt_get_block_size mcrypt_get_cipher_name mcrypt_get_iv_size mcrypt_get_key_size mcrypt_gost mcrypt_idea mcrypt_list_algorithms mcrypt_list_modes mcrypt_loki97 mcrypt_mars mcrypt_mode_cbc mcrypt_mode_cfb mcrypt_mode_ecb mcrypt_mode_nofb mcrypt_mode_ofb mcrypt_mode_stream mcrypt_module_close mcrypt_module_get_algo_block_size mcrypt_module_get_algo_key_size mcrypt_module_get_supported_key_sizes mcrypt_module_is_block_algorithm mcrypt_module_is_block_algorithm_mode mcrypt_module_is_block_mode mcrypt_module_open mcrypt_module_self_test mcrypt_ofb mcrypt_panama mcrypt_rand mcrypt_rc2 mcrypt_rc6 mcrypt_rijndael_128 mcrypt_rijndael_192 mcrypt_rijndael_256 mcrypt_safer128 mcrypt_safer64 mcrypt_saferplus mcrypt_serpent mcrypt_skipjack mcrypt_threeway mcrypt_tripledes mcrypt_twofish mcrypt_wake mcrypt_xtea md5 md5_file mdecrypt_generic memcache_add memcache_add_server memcache_append memcache_cas memcache_close memcache_compressed memcache_connect memcache_debug memcache_decrement memcache_delete memcache_flush memcache_get memcache_get_extended_stats memcache_get_server_status memcache_get_stats memcache_get_version memcache_have_session memcache_increment memcache_pconnect memcache_prepend memcache_replace memcache_set memcache_set_compress_threshold memcache_set_failure_callback memcache_set_server_params memory_get_peak_usage memory_get_usage memory_trace metaphone method_exists mhash mhash_adler32 mhash_count mhash_crc32 mhash_crc32b mhash_fnv132 mhash_fnv164 mhash_fnv1a32 mhash_fnv1a64 mhash_get_block_size mhash_get_hash_name mhash_gost mhash_haval128 mhash_haval160 mhash_haval192 mhash_haval224 mhash_haval256 mhash_joaat mhash_keygen_s2k mhash_md2 mhash_md4 mhash_md5 mhash_ripemd128 mhash_ripemd160 mhash_ripemd256 mhash_ripemd320 mhash_sha1 mhash_sha224 mhash_sha256 mhash_sha384 mhash_sha512 mhash_snefru256 mhash_tiger mhash_tiger128 mhash_tiger160 mhash_whirlpool microtime mime_content_type min ming_keypress ming_new ming_setcubicthreshold ming_setscale ming_setswfcompression ming_useconstants ming_useswfversion ming_zlib mk_e_unavailable mkdir mktime mon_1 mon_10 mon_11 mon_12 mon_2 mon_3 mon_4 mon_5 mon_6 mon_7 mon_8 mon_9 mon_decimal_point mon_grouping mon_thousands_sep money_format mongo_stream_notify_io_completed mongo_stream_notify_io_progress mongo_stream_notify_io_read mongo_stream_notify_io_write mongo_stream_notify_log_batchinsert mongo_stream_notify_log_cmd_delete mongo_stream_notify_log_cmd_insert mongo_stream_notify_log_cmd_update mongo_stream_notify_log_delete mongo_stream_notify_log_getmore mongo_stream_notify_log_insert mongo_stream_notify_log_killcursor mongo_stream_notify_log_query mongo_stream_notify_log_response_header mongo_stream_notify_log_update mongo_stream_notify_log_write_batch mongo_stream_notify_log_write_reply mongo_stream_notify_type_io_init mongo_stream_notify_type_log mongo_streams mongo_supports_auth_mechanism_gssapi mongo_supports_auth_mechanism_mongodb_cr mongo_supports_auth_mechanism_mongodb_x509 mongo_supports_auth_mechanism_plain mongo_supports_ssl mongo_supports_streams move_uploaded_file mqseries_back mqseries_begin mqseries_close mqseries_cmit mqseries_conn mqseries_connx mqseries_disc mqseries_get mqseries_inq mqseries_mqcc_failed mqseries_mqcc_ok mqseries_mqcc_unknown mqseries_mqcc_warning mqseries_open mqseries_put mqseries_put1 mqseries_set mqseries_strerror msession_connect msession_count msession_create msession_destroy msession_disconnect msession_find msession_get msession_get_array msession_get_data msession_inc msession_list msession_listvar msession_lock msession_plugin msession_randstr msession_set msession_set_array msession_set_data msession_timeout msession_uniq msession_unlock msg_ctrunc msg_dontroute msg_dontwait msg_eagain msg_enomsg msg_eof msg_eor msg_except msg_get_queue msg_ipc_nowait msg_noerror msg_oob msg_peek msg_queue_exists msg_receive msg_remove_queue msg_send msg_set_queue msg_stat_queue msg_trunc msg_waitall msgfmt_create msgfmt_format msgfmt_format_message msgfmt_get_error_code msgfmt_get_error_message msgfmt_get_locale msgfmt_get_pattern msgfmt_parse msgfmt_parse_message msgfmt_set_pattern msql msql_affected_rows msql_assoc msql_both msql_close msql_connect msql_create_db msql_createdb msql_data_seek msql_db_query msql_dbname msql_drop_db msql_error msql_fetch_array msql_fetch_field msql_fetch_object msql_fetch_row msql_field_flags msql_field_len msql_field_name msql_field_seek msql_field_table msql_field_type msql_fieldflags msql_fieldlen msql_fieldname msql_fieldtable msql_fieldtype msql_free_result msql_list_dbs msql_list_fields msql_list_tables msql_num msql_num_fields msql_num_rows msql_numfields msql_numrows msql_pconnect msql_query msql_regcase msql_result msql_select_db msql_tablename mssql_assoc mssql_bind mssql_both mssql_close mssql_connect mssql_data_seek mssql_execute mssql_fetch_array mssql_fetch_assoc mssql_fetch_batch mssql_fetch_field mssql_fetch_object mssql_fetch_row mssql_field_length mssql_field_name mssql_field_seek mssql_field_type mssql_free_result mssql_free_statement mssql_get_last_message mssql_guid_string mssql_init mssql_min_error_severity mssql_min_message_severity mssql_next_result mssql_num mssql_num_fields mssql_num_rows mssql_pconnect mssql_query mssql_result mssql_rows_affected mssql_select_db mt_getrandmax mt_rand mt_srand mysql mysql_affected_rows mysql_assoc mysql_both mysql_client_compress mysql_client_encoding mysql_client_ignore_space mysql_client_interactive mysql_client_ssl mysql_close mysql_connect mysql_create_db mysql_data_seek mysql_db_name mysql_db_query mysql_dbname mysql_drop_db mysql_errno mysql_error mysql_escape_string mysql_fetch_array mysql_fetch_assoc mysql_fetch_field mysql_fetch_lengths mysql_fetch_object mysql_fetch_row mysql_field_flags mysql_field_len mysql_field_name mysql_field_seek mysql_field_table mysql_field_type mysql_fieldflags mysql_fieldlen mysql_fieldname mysql_fieldtable mysql_fieldtype mysql_free_result mysql_freeresult mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql_insert_id mysql_list_dbs mysql_list_fields mysql_list_processes mysql_list_tables mysql_listdbs mysql_listfields mysql_listtables mysql_num mysql_num_fields mysql_num_rows mysql_numfields mysql_numrows mysql_pconnect mysql_ping mysql_query mysql_real_escape_string mysql_result mysql_select_db mysql_selectdb mysql_set_charset mysql_stat mysql_table_name mysql_tablename mysql_thread_id mysql_unbuffered_query mysqli_affected_rows mysqli_assoc mysqli_async mysqli_auto_increment_flag mysqli_autocommit mysqli_begin_transaction mysqli_binary_flag mysqli_bind_param mysqli_bind_result mysqli_blob_flag mysqli_both mysqli_change_user mysqli_character_set_name mysqli_client_can_handle_expired_passwords mysqli_client_compress mysqli_client_encoding mysqli_client_found_rows mysqli_client_ignore_space mysqli_client_interactive mysqli_client_multi_queries mysqli_client_no_schema mysqli_client_ssl mysqli_close mysqli_commit mysqli_connect mysqli_connect_errno mysqli_connect_error mysqli_cursor_type_for_update mysqli_cursor_type_no_cursor mysqli_cursor_type_read_only mysqli_cursor_type_scrollable mysqli_data_seek mysqli_data_truncated mysqli_debug mysqli_debug_trace_enabled mysqli_dump_debug_info mysqli_embedded_server_end mysqli_embedded_server_start mysqli_enum_flag mysqli_errno mysqli_error mysqli_error_list mysqli_escape_string mysqli_execute mysqli_fetch mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field mysqli_fetch_field_direct mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_cache_stats mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_links_stats mysqli_get_metadata mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_get_warnings mysqli_group_flag mysqli_info mysqli_init mysqli_init_command mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_multiple_key_flag mysqli_need_data mysqli_next_result mysqli_no_data mysqli_no_default_value_flag mysqli_not_null_flag mysqli_num mysqli_num_fields mysqli_num_flag mysqli_num_rows mysqli_on_update_now_flag mysqli_opt_can_handle_expired_passwords mysqli_opt_connect_timeout mysqli_opt_int_and_float_native mysqli_opt_local_infile mysqli_opt_net_cmd_buffer_size mysqli_opt_net_read_buffer_size mysqli_opt_ssl_verify_server_cert mysqli_options mysqli_param_count mysqli_part_key_flag mysqli_ping mysqli_poll mysqli_prepare mysqli_pri_key_flag mysqli_query mysqli_read_default_file mysqli_read_default_group mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_refresh_backup_log mysqli_refresh_grant mysqli_refresh_hosts mysqli_refresh_log mysqli_refresh_master mysqli_refresh_slave mysqli_refresh_status mysqli_refresh_tables mysqli_refresh_threads mysqli_release_savepoint mysqli_report mysqli_report_all mysqli_report_error mysqli_report_index mysqli_report_off mysqli_report_strict mysqli_rollback mysqli_savepoint mysqli_select_db mysqli_send_long_data mysqli_server_ps_out_params mysqli_server_public_key mysqli_server_query_no_good_index_used mysqli_server_query_no_index_used mysqli_server_query_was_slow mysqli_set_charset mysqli_set_charset_dir mysqli_set_charset_name mysqli_set_flag mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_set_opt mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_affected_rows mysqli_stmt_attr_cursor_type mysqli_stmt_attr_get mysqli_stmt_attr_prefetch_rows mysqli_stmt_attr_set mysqli_stmt_attr_update_max_length mysqli_stmt_bind_param mysqli_stmt_bind_result mysqli_stmt_close mysqli_stmt_data_seek mysqli_stmt_errno mysqli_stmt_error mysqli_stmt_error_list mysqli_stmt_execute mysqli_stmt_fetch mysqli_stmt_field_count mysqli_stmt_free_result mysqli_stmt_get_result mysqli_stmt_get_warnings mysqli_stmt_init mysqli_stmt_insert_id mysqli_stmt_more_results mysqli_stmt_next_result mysqli_stmt_num_rows mysqli_stmt_param_count mysqli_stmt_prepare mysqli_stmt_reset mysqli_stmt_result_metadata mysqli_stmt_send_long_data mysqli_stmt_sqlstate mysqli_stmt_store_result mysqli_store_result mysqli_store_result_copy_data mysqli_thread_id mysqli_thread_safe mysqli_timestamp_flag mysqli_trans_cor_and_chain mysqli_trans_cor_and_no_chain mysqli_trans_cor_no_release mysqli_trans_cor_release mysqli_trans_start_read_only mysqli_trans_start_read_write mysqli_trans_start_with_consistent_snapshot mysqli_type_bit mysqli_type_blob mysqli_type_char mysqli_type_date mysqli_type_datetime mysqli_type_decimal mysqli_type_double mysqli_type_enum mysqli_type_float mysqli_type_geometry mysqli_type_int24 mysqli_type_interval mysqli_type_long mysqli_type_long_blob mysqli_type_longlong mysqli_type_medium_blob mysqli_type_newdate mysqli_type_newdecimal mysqli_type_null mysqli_type_set mysqli_type_short mysqli_type_string mysqli_type_time mysqli_type_timestamp mysqli_type_tiny mysqli_type_tiny_blob mysqli_type_var_string mysqli_type_year mysqli_unique_key_flag mysqli_unsigned_flag mysqli_use_result mysqli_warning_count mysqli_zerofill_flag n_cs_precedes n_sep_by_space n_sign_posn namespace nan natcasesort natsort ncurses_addch ncurses_addchnstr ncurses_addchstr ncurses_addnstr ncurses_addstr ncurses_all_mouse_events ncurses_assume_default_colors ncurses_attroff ncurses_attron ncurses_attrset ncurses_baudrate ncurses_beep ncurses_bkgd ncurses_bkgdset ncurses_border ncurses_bottom_panel ncurses_button1_clicked ncurses_button1_double_clicked ncurses_button1_pressed ncurses_button1_released ncurses_button1_triple_clicked ncurses_button_alt ncurses_button_ctrl ncurses_button_shift ncurses_can_change_color ncurses_cbreak ncurses_clear ncurses_clrtobot ncurses_clrtoeol ncurses_color_black ncurses_color_blue ncurses_color_content ncurses_color_cyan ncurses_color_green ncurses_color_magenta ncurses_color_red ncurses_color_set ncurses_color_white ncurses_color_yellow ncurses_curs_set ncurses_def_prog_mode ncurses_def_shell_mode ncurses_define_key ncurses_del_panel ncurses_delay_output ncurses_delch ncurses_deleteln ncurses_delwin ncurses_doupdate ncurses_echo ncurses_echochar ncurses_end ncurses_erase ncurses_erasechar ncurses_filter ncurses_flash ncurses_flushinp ncurses_getch ncurses_getmaxyx ncurses_getmouse ncurses_getyx ncurses_halfdelay ncurses_has_colors ncurses_has_ic ncurses_has_il ncurses_has_key ncurses_hide_panel ncurses_hline ncurses_inch ncurses_init ncurses_init_color ncurses_init_pair ncurses_insch ncurses_insdelln ncurses_insertln ncurses_insstr ncurses_instr ncurses_isendwin ncurses_key_a1 ncurses_key_a3 ncurses_key_b2 ncurses_key_backspace ncurses_key_beg ncurses_key_btab ncurses_key_c1 ncurses_key_c3 ncurses_key_cancel ncurses_key_catab ncurses_key_clear ncurses_key_close ncurses_key_command ncurses_key_copy ncurses_key_create ncurses_key_ctab ncurses_key_dc ncurses_key_dl ncurses_key_down ncurses_key_eic ncurses_key_end ncurses_key_eol ncurses_key_eos ncurses_key_exit ncurses_key_f0 ncurses_key_find ncurses_key_help ncurses_key_home ncurses_key_ic ncurses_key_il ncurses_key_left ncurses_key_ll ncurses_key_mark ncurses_key_max ncurses_key_message ncurses_key_mouse ncurses_key_move ncurses_key_next ncurses_key_npage ncurses_key_open ncurses_key_options ncurses_key_ppage ncurses_key_previous ncurses_key_print ncurses_key_redo ncurses_key_reference ncurses_key_refresh ncurses_key_replace ncurses_key_reset ncurses_key_restart ncurses_key_resume ncurses_key_right ncurses_key_save ncurses_key_sbeg ncurses_key_scancel ncurses_key_scommand ncurses_key_scopy ncurses_key_screate ncurses_key_sdc ncurses_key_sdl ncurses_key_select ncurses_key_send ncurses_key_seol ncurses_key_sexit ncurses_key_sf ncurses_key_sfind ncurses_key_shelp ncurses_key_shome ncurses_key_sic ncurses_key_sleft ncurses_key_smessage ncurses_key_smove ncurses_key_snext ncurses_key_soptions ncurses_key_sprevious ncurses_key_sprint ncurses_key_sr ncurses_key_sredo ncurses_key_sreplace ncurses_key_sreset ncurses_key_sright ncurses_key_srsume ncurses_key_ssave ncurses_key_ssuspend ncurses_key_stab ncurses_key_undo ncurses_key_up ncurses_keyok ncurses_keypad ncurses_killchar ncurses_longname ncurses_meta ncurses_mouse_trafo ncurses_mouseinterval ncurses_mousemask ncurses_move ncurses_move_panel ncurses_mvaddch ncurses_mvaddchnstr ncurses_mvaddchstr ncurses_mvaddnstr ncurses_mvaddstr ncurses_mvcur ncurses_mvdelch ncurses_mvgetch ncurses_mvhline ncurses_mvinch ncurses_mvvline ncurses_mvwaddstr ncurses_napms ncurses_new_panel ncurses_newpad ncurses_newwin ncurses_nl ncurses_nocbreak ncurses_noecho ncurses_nonl ncurses_noqiflush ncurses_noraw ncurses_pair_content ncurses_panel_above ncurses_panel_below ncurses_panel_window ncurses_pnoutrefresh ncurses_prefresh ncurses_putp ncurses_qiflush ncurses_raw ncurses_refresh ncurses_replace_panel ncurses_report_mouse_position ncurses_reset_prog_mode ncurses_reset_shell_mode ncurses_resetty ncurses_savetty ncurses_scr_dump ncurses_scr_init ncurses_scr_restore ncurses_scr_set ncurses_scrl ncurses_show_panel ncurses_slk_attr ncurses_slk_attroff ncurses_slk_attron ncurses_slk_attrset ncurses_slk_clear ncurses_slk_color ncurses_slk_init ncurses_slk_noutrefresh ncurses_slk_refresh ncurses_slk_restore ncurses_slk_set ncurses_slk_touch ncurses_standend ncurses_standout ncurses_start_color ncurses_termattrs ncurses_termname ncurses_timeout ncurses_top_panel ncurses_typeahead ncurses_ungetch ncurses_ungetmouse ncurses_update_panels ncurses_use_default_colors ncurses_use_env ncurses_use_extended_names ncurses_vidattr ncurses_vline ncurses_waddch ncurses_waddstr ncurses_wattroff ncurses_wattron ncurses_wattrset ncurses_wborder ncurses_wclear ncurses_wcolor_set ncurses_werase ncurses_wgetch ncurses_whline ncurses_wmouse_trafo ncurses_wmove ncurses_wnoutrefresh ncurses_wrefresh ncurses_wstandend ncurses_wstandout ncurses_wvline negative_sign new newt_anchor_bottom newt_anchor_left newt_anchor_right newt_anchor_top newt_arg_append newt_arg_last newt_bell newt_button newt_button_bar newt_centered_window newt_checkbox newt_checkbox_get_value newt_checkbox_set_flags newt_checkbox_set_value newt_checkbox_tree newt_checkbox_tree_add_item newt_checkbox_tree_find_item newt_checkbox_tree_get_current newt_checkbox_tree_get_entry_value newt_checkbox_tree_get_multi_selection newt_checkbox_tree_get_selection newt_checkbox_tree_multi newt_checkbox_tree_set_current newt_checkbox_tree_set_entry newt_checkbox_tree_set_entry_value newt_checkbox_tree_set_width newt_checkboxtree_collapsed newt_checkboxtree_expanded newt_checkboxtree_hide_box newt_checkboxtree_selected newt_checkboxtree_unselectable newt_checkboxtree_unselected newt_clear_key_buffer newt_cls newt_colorset_actbutton newt_colorset_actcheckbox newt_colorset_actlistbox newt_colorset_actsellistbox newt_colorset_acttextbox newt_colorset_border newt_colorset_button newt_colorset_checkbox newt_colorset_compactbutton newt_colorset_disentry newt_colorset_emptyscale newt_colorset_entry newt_colorset_fullscale newt_colorset_helpline newt_colorset_label newt_colorset_listbox newt_colorset_root newt_colorset_roottext newt_colorset_sellistbox newt_colorset_shadow newt_colorset_textbox newt_colorset_title newt_colorset_window newt_compact_button newt_component_add_callback newt_component_takes_focus newt_create_grid newt_cursor_off newt_cursor_on newt_delay newt_draw_form newt_draw_root_text newt_entry newt_entry_disabled newt_entry_get_value newt_entry_hidden newt_entry_returnexit newt_entry_scroll newt_entry_set newt_entry_set_filter newt_entry_set_flags newt_exit_component newt_exit_fdready newt_exit_hotkey newt_exit_timer newt_fd_except newt_fd_read newt_fd_write newt_finished newt_flag_border newt_flag_checkbox newt_flag_disabled newt_flag_hidden newt_flag_multiple newt_flag_nof12 newt_flag_password newt_flag_returnexit newt_flag_scroll newt_flag_selected newt_flag_showcursor newt_flag_wrap newt_flags_reset newt_flags_set newt_flags_toggle newt_form newt_form_add_component newt_form_add_components newt_form_add_hot_key newt_form_destroy newt_form_get_current newt_form_nof12 newt_form_run newt_form_set_background newt_form_set_height newt_form_set_size newt_form_set_timer newt_form_set_width newt_form_watch_fd newt_get_screen_size newt_grid_add_components_to_form newt_grid_basic_window newt_grid_component newt_grid_empty newt_grid_flag_growx newt_grid_flag_growy newt_grid_free newt_grid_get_size newt_grid_h_close_stacked newt_grid_h_stacked newt_grid_place newt_grid_set_field newt_grid_simple_window newt_grid_subgrid newt_grid_v_close_stacked newt_grid_v_stacked newt_grid_wrapped_window newt_grid_wrapped_window_at newt_init newt_key_bkspc newt_key_delete newt_key_down newt_key_end newt_key_enter newt_key_escape newt_key_extra_base newt_key_f1 newt_key_f10 newt_key_f11 newt_key_f12 newt_key_f2 newt_key_f3 newt_key_f4 newt_key_f5 newt_key_f6 newt_key_f7 newt_key_f8 newt_key_f9 newt_key_home newt_key_insert newt_key_left newt_key_pgdn newt_key_pgup newt_key_resize newt_key_return newt_key_right newt_key_suspend newt_key_tab newt_key_untab newt_key_up newt_label newt_label_set_text newt_listbox newt_listbox_append_entry newt_listbox_clear newt_listbox_clear_selection newt_listbox_delete_entry newt_listbox_get_current newt_listbox_get_selection newt_listbox_insert_entry newt_listbox_item_count newt_listbox_returnexit newt_listbox_select_item newt_listbox_set_current newt_listbox_set_current_by_key newt_listbox_set_data newt_listbox_set_entry newt_listbox_set_width newt_listitem newt_listitem_get_data newt_listitem_set newt_open_window newt_pop_help_line newt_pop_window newt_push_help_line newt_radio_get_current newt_radiobutton newt_redraw_help_line newt_reflow_text newt_refresh newt_resize_screen newt_resume newt_run_form newt_scale newt_scale_set newt_scrollbar_set newt_set_help_callback newt_set_suspend_callback newt_suspend newt_textbox newt_textbox_get_num_lines newt_textbox_reflowed newt_textbox_scroll newt_textbox_set_height newt_textbox_set_text newt_textbox_wrap newt_vertical_scrollbar newt_wait_for_key newt_win_choice newt_win_entries newt_win_menu newt_win_message newt_win_messagev newt_win_ternary next ngettext nil nl2br nl_langinfo noexpr norm_ignorecase norm_ignorekanatype norm_ignorekashida norm_ignorenonspace norm_ignoresymbols norm_ignorewidth normalizer_is_normalized normalizer_normalize nostr nthmac null number_format numfmt_create numfmt_format numfmt_format_currency numfmt_get_attribute numfmt_get_error_code numfmt_get_error_message numfmt_get_locale numfmt_get_pattern numfmt_get_symbol numfmt_get_text_attribute numfmt_parse numfmt_parse_currency numfmt_set_attribute numfmt_set_pattern numfmt_set_symbol numfmt_set_text_attribute o_append o_async o_creat o_excl o_ndelay o_noctty o_nonblock o_rdonly o_rdwr o_sync o_trunc o_wronly ob_clean ob_deflatehandler ob_end_clean ob_end_flush ob_etaghandler ob_flush ob_get_clean ob_get_contents ob_get_flush ob_get_length ob_get_level ob_get_status ob_gzhandler ob_iconv_handler ob_implicit_flush ob_inflatehandler ob_list_handlers ob_start ob_tidyhandler object oci_assoc oci_b_bfile oci_b_bin oci_b_blob oci_b_bol oci_b_cfilee oci_b_clob oci_b_cursor oci_b_int oci_b_nty oci_b_num oci_b_rowid oci_bind_array_by_name oci_bind_by_name oci_both oci_cancel oci_client_version oci_close oci_commit oci_commit_on_success oci_connect oci_cred_ext oci_d_file oci_d_lob oci_d_rowid oci_default oci_define_by_name oci_describe_only oci_dtype_file oci_dtype_lob oci_dtype_rowid oci_error oci_exact_fetch oci_execute oci_fetch oci_fetch_all oci_fetch_array oci_fetch_assoc oci_fetch_object oci_fetch_row oci_fetchstatement_by_column oci_fetchstatement_by_row oci_field_is_null oci_field_name oci_field_precision oci_field_scale oci_field_size oci_field_type oci_field_type_raw oci_free_descriptor oci_free_statement oci_get_implicit_resultset oci_internal_debug oci_lob_buffer_free oci_lob_copy oci_lob_is_equal oci_new_collection oci_new_connect oci_new_cursor oci_new_descriptor oci_no_auto_commit oci_num oci_num_fields oci_num_rows oci_parse oci_password_change oci_pconnect oci_result oci_return_lobs oci_return_nulls oci_rollback oci_seek_cur oci_seek_end oci_seek_set oci_server_version oci_set_action oci_set_client_identifier oci_set_client_info oci_set_edition oci_set_module_name oci_set_prefetch oci_statement_type oci_sysdate oci_sysdba oci_sysoper oci_temp_blob oci_temp_clob ocibindbyname ocicolumnisnull ocicolumnname ocicolumnsize ocicolumntype ocicommit ocidefinebyname ocierror ociexecute ocifetch ocifetchinto ocifetchstatement ocifreestatement ocilogoff ocilogon ocinewcursor ocinewdescriptor ocinlogon ocinumcols ociparse ociplogon ociresult ocirollback ocirowcount ociserverversion ocistatementtype octdec odbc_autocommit odbc_binmode odbc_binmode_convert odbc_binmode_passthru odbc_binmode_return odbc_close odbc_close_all odbc_columnprivileges odbc_columns odbc_commit odbc_connect odbc_cursor odbc_data_source odbc_do odbc_error odbc_errormsg odbc_exec odbc_execute odbc_fetch_array odbc_fetch_into odbc_fetch_object odbc_fetch_row odbc_field_len odbc_field_name odbc_field_num odbc_field_precision odbc_field_scale odbc_field_type odbc_foreignkeys odbc_free_result odbc_gettypeinfo odbc_longreadlen odbc_next_result odbc_num_fields odbc_num_rows odbc_pconnect odbc_prepare odbc_primarykeys odbc_procedurecolumns odbc_procedures odbc_result odbc_result_all odbc_rollback odbc_setoption odbc_specialcolumns odbc_statistics odbc_tableprivileges odbc_tables odbc_type oggvorbis_pcm_s16_be oggvorbis_pcm_s16_le oggvorbis_pcm_s8 oggvorbis_pcm_u16_be oggvorbis_pcm_u16_le oggvorbis_pcm_u8 old_function op_anonymous op_debug op_expunge op_halfopen op_prototype op_readonly op_secure op_shortcache op_silent opcache_compile_file opcache_get_configuration opcache_get_status opcache_invalidate opcache_is_script_cached opcache_reset openal_buffer_create openal_buffer_data openal_buffer_destroy openal_buffer_get openal_buffer_loadwav openal_context_create openal_context_current openal_context_destroy openal_context_process openal_context_suspend openal_device_close openal_device_open openal_listener_get openal_listener_set openal_source_create openal_source_destroy openal_source_get openal_source_pause openal_source_play openal_source_rewind openal_source_set openal_source_stop openal_stream opendir openlog openssl_algo_dss1 openssl_algo_md4 openssl_algo_md5 openssl_algo_rmd160 openssl_algo_sha1 openssl_algo_sha224 openssl_algo_sha256 openssl_algo_sha384 openssl_algo_sha512 openssl_cipher_3des openssl_cipher_aes_128_cbc openssl_cipher_aes_192_cbc openssl_cipher_aes_256_cbc openssl_cipher_des openssl_cipher_iv_length openssl_cipher_rc2_128 openssl_cipher_rc2_40 openssl_cipher_rc2_64 openssl_csr_export openssl_csr_export_to_file openssl_csr_get_public_key openssl_csr_get_subject openssl_csr_new openssl_csr_sign openssl_decrypt openssl_default_stream_ciphers openssl_dh_compute_key openssl_digest openssl_encrypt openssl_error_string openssl_free_key openssl_get_cert_locations openssl_get_cipher_methods openssl_get_md_methods openssl_get_privatekey openssl_get_publickey openssl_keytype_dh openssl_keytype_dsa openssl_keytype_ec openssl_keytype_rsa openssl_no_padding openssl_open openssl_pbkdf2 openssl_pkcs12_export openssl_pkcs12_export_to_file openssl_pkcs12_read openssl_pkcs1_oaep_padding openssl_pkcs1_padding openssl_pkcs7_decrypt openssl_pkcs7_encrypt openssl_pkcs7_sign openssl_pkcs7_verify openssl_pkey_export openssl_pkey_export_to_file openssl_pkey_free openssl_pkey_get_details openssl_pkey_get_private openssl_pkey_get_public openssl_pkey_new openssl_private_decrypt openssl_private_encrypt openssl_public_decrypt openssl_public_encrypt openssl_random_pseudo_bytes openssl_raw_data openssl_seal openssl_sign openssl_spki_export openssl_spki_export_challenge openssl_spki_new openssl_spki_verify openssl_sslv23_padding openssl_tlsext_server_name openssl_verify openssl_version_number openssl_version_text openssl_x509_check_private_key openssl_x509_checkpurpose openssl_x509_export openssl_x509_export_to_file openssl_x509_fingerprint openssl_x509_free openssl_x509_parse openssl_x509_read openssl_zero_padding or ord output_add_rewrite_var output_reset_rewrite_vars override_function p_cs_precedes p_sep_by_space p_sign_posn pack parent parse_ini_file parse_ini_string parse_str parse_url parsekit_compile_file parsekit_compile_string parsekit_extended_value parsekit_func_arginfo parsekit_is_const parsekit_is_tmp_var parsekit_is_unused parsekit_is_var parsekit_quiet parsekit_result_const parsekit_result_ea_type parsekit_result_jmp_addr parsekit_result_oparray parsekit_result_opline parsekit_result_var parsekit_simple parsekit_usage_unknown parsekit_zend_add parsekit_zend_add_array_element parsekit_zend_add_char parsekit_zend_add_interface parsekit_zend_add_string parsekit_zend_add_var parsekit_zend_assign parsekit_zend_assign_add parsekit_zend_assign_bw_and parsekit_zend_assign_bw_or parsekit_zend_assign_bw_xor parsekit_zend_assign_concat parsekit_zend_assign_dim parsekit_zend_assign_div parsekit_zend_assign_mod parsekit_zend_assign_mul parsekit_zend_assign_obj parsekit_zend_assign_ref parsekit_zend_assign_sl parsekit_zend_assign_sr parsekit_zend_assign_sub parsekit_zend_begin_silence parsekit_zend_bool parsekit_zend_bool_not parsekit_zend_bool_xor parsekit_zend_brk parsekit_zend_bw_and parsekit_zend_bw_not parsekit_zend_bw_or parsekit_zend_bw_xor parsekit_zend_case parsekit_zend_cast parsekit_zend_catch parsekit_zend_clone parsekit_zend_concat parsekit_zend_cont parsekit_zend_declare_class parsekit_zend_declare_function parsekit_zend_declare_inherited_class parsekit_zend_div parsekit_zend_do_fcall parsekit_zend_do_fcall_by_name parsekit_zend_echo parsekit_zend_end_silence parsekit_zend_eval_code parsekit_zend_exit parsekit_zend_ext_fcall_begin parsekit_zend_ext_fcall_end parsekit_zend_ext_nop parsekit_zend_ext_stmt parsekit_zend_fe_fetch parsekit_zend_fe_reset parsekit_zend_fetch_class parsekit_zend_fetch_constant parsekit_zend_fetch_dim_func_arg parsekit_zend_fetch_dim_is parsekit_zend_fetch_dim_r parsekit_zend_fetch_dim_rw parsekit_zend_fetch_dim_tmp_var parsekit_zend_fetch_dim_unset parsekit_zend_fetch_dim_w parsekit_zend_fetch_func_arg parsekit_zend_fetch_is parsekit_zend_fetch_obj_func_arg parsekit_zend_fetch_obj_is parsekit_zend_fetch_obj_r parsekit_zend_fetch_obj_rw parsekit_zend_fetch_obj_unset parsekit_zend_fetch_obj_w parsekit_zend_fetch_r parsekit_zend_fetch_rw parsekit_zend_fetch_unset parsekit_zend_fetch_w parsekit_zend_free parsekit_zend_handle_exception parsekit_zend_import_class parsekit_zend_import_const parsekit_zend_import_function parsekit_zend_include_or_eval parsekit_zend_init_array parsekit_zend_init_ctor_call parsekit_zend_init_fcall_by_name parsekit_zend_init_method_call parsekit_zend_init_static_method_call parsekit_zend_init_string parsekit_zend_instanceof parsekit_zend_internal_class parsekit_zend_internal_function parsekit_zend_is_equal parsekit_zend_is_identical parsekit_zend_is_not_equal parsekit_zend_is_not_identical parsekit_zend_is_smaller parsekit_zend_is_smaller_or_equal parsekit_zend_isset_isempty parsekit_zend_isset_isempty_dim_obj parsekit_zend_isset_isempty_prop_obj parsekit_zend_isset_isempty_var parsekit_zend_jmp parsekit_zend_jmp_no_ctor parsekit_zend_jmpnz parsekit_zend_jmpnz_ex parsekit_zend_jmpz parsekit_zend_jmpz_ex parsekit_zend_jmpznz parsekit_zend_mod parsekit_zend_mul parsekit_zend_new parsekit_zend_nop parsekit_zend_op_data parsekit_zend_overloaded_function parsekit_zend_overloaded_function_temporary parsekit_zend_post_dec parsekit_zend_post_dec_obj parsekit_zend_post_inc parsekit_zend_post_inc_obj parsekit_zend_pre_dec parsekit_zend_pre_dec_obj parsekit_zend_pre_inc parsekit_zend_pre_inc_obj parsekit_zend_print parsekit_zend_qm_assign parsekit_zend_raise_abstract_error parsekit_zend_recv parsekit_zend_recv_init parsekit_zend_return parsekit_zend_send_ref parsekit_zend_send_val parsekit_zend_send_var parsekit_zend_send_var_no_ref parsekit_zend_sl parsekit_zend_sr parsekit_zend_sub parsekit_zend_switch_free parsekit_zend_throw parsekit_zend_ticks parsekit_zend_unset_dim_obj parsekit_zend_unset_var parsekit_zend_user_class parsekit_zend_user_function parsekit_zend_verify_abstract_class passthru password_bcrypt password_bcrypt_default_cost password_default password_get_info password_hash password_needs_rehash password_verify path_separator pathinfo pathinfo_basename pathinfo_dirname pathinfo_extension pathinfo_filename pclose pcntl_alarm pcntl_errno pcntl_exec pcntl_fork pcntl_get_last_error pcntl_getpriority pcntl_setpriority pcntl_signal pcntl_signal_dispatch pcntl_sigprocmask pcntl_sigtimedwait pcntl_sigwaitinfo pcntl_strerror pcntl_wait pcntl_waitpid pcntl_wexitstatus pcntl_wifexited pcntl_wifsignaled pcntl_wifstopped pcntl_wstopsig pcntl_wtermsig pcre_version pdf_activate_item pdf_add_annotation pdf_add_bookmark pdf_add_launchlink pdf_add_locallink pdf_add_nameddest pdf_add_note pdf_add_outline pdf_add_pdflink pdf_add_table_cell pdf_add_textflow pdf_add_thumbnail pdf_add_weblink pdf_arc pdf_arcn pdf_attach_file pdf_begin_document pdf_begin_font pdf_begin_glyph pdf_begin_item pdf_begin_layer pdf_begin_page pdf_begin_page_ext pdf_begin_pattern pdf_begin_template pdf_begin_template_ext pdf_circle pdf_clip pdf_close pdf_close_image pdf_close_pdi pdf_close_pdi_page pdf_closepath pdf_closepath_fill_stroke pdf_closepath_stroke pdf_concat pdf_continue_text pdf_create_3dview pdf_create_action pdf_create_annotation pdf_create_bookmark pdf_create_field pdf_create_fieldgroup pdf_create_gstate pdf_create_pvf pdf_create_textflow pdf_curveto pdf_define_layer pdf_delete pdf_delete_pvf pdf_delete_table pdf_delete_textflow pdf_encoding_set_char pdf_end_document pdf_end_font pdf_end_glyph pdf_end_item pdf_end_layer pdf_end_page pdf_end_page_ext pdf_end_pattern pdf_end_template pdf_endpath pdf_fill pdf_fill_imageblock pdf_fill_pdfblock pdf_fill_stroke pdf_fill_textblock pdf_findfont pdf_fit_image pdf_fit_pdi_page pdf_fit_table pdf_fit_textflow pdf_fit_textline pdf_get_apiname pdf_get_buffer pdf_get_errmsg pdf_get_errnum pdf_get_font pdf_get_fontname pdf_get_fontsize pdf_get_image_height pdf_get_image_width pdf_get_majorversion pdf_get_minorversion pdf_get_parameter pdf_get_pdi_parameter pdf_get_pdi_value pdf_get_value pdf_info_font pdf_info_matchbox pdf_info_table pdf_info_textflow pdf_info_textline pdf_initgraphics pdf_lineto pdf_load_3ddata pdf_load_font pdf_load_iccprofile pdf_load_image pdf_makespotcolor pdf_moveto pdf_new pdf_open_ccitt pdf_open_file pdf_open_gif pdf_open_image pdf_open_image_file pdf_open_jpeg pdf_open_memory_image pdf_open_pdi pdf_open_pdi_document pdf_open_pdi_page pdf_open_tiff pdf_pcos_get_number pdf_pcos_get_stream pdf_pcos_get_string pdf_place_image pdf_place_pdi_page pdf_process_pdi pdf_rect pdf_restore pdf_resume_page pdf_rotate pdf_save pdf_scale pdf_set_border_color pdf_set_border_dash pdf_set_border_style pdf_set_char_spacing pdf_set_duration pdf_set_gstate pdf_set_horiz_scaling pdf_set_info pdf_set_info_author pdf_set_info_creator pdf_set_info_keywords pdf_set_info_subject pdf_set_info_title pdf_set_layer_dependency pdf_set_leading pdf_set_parameter pdf_set_text_matrix pdf_set_text_pos pdf_set_text_rendering pdf_set_text_rise pdf_set_value pdf_set_word_spacing pdf_setcolor pdf_setdash pdf_setdashpattern pdf_setflat pdf_setfont pdf_setgray pdf_setgray_fill pdf_setgray_stroke pdf_setlinecap pdf_setlinejoin pdf_setlinewidth pdf_setmatrix pdf_setmiterlimit pdf_setpolydash pdf_setrgbcolor pdf_setrgbcolor_fill pdf_setrgbcolor_stroke pdf_shading pdf_shading_pattern pdf_shfill pdf_show pdf_show_boxed pdf_show_xy pdf_skew pdf_stringwidth pdf_stroke pdf_suspend_page pdf_translate pdf_utf16_to_utf8 pdf_utf32_to_utf16 pdf_utf8_to_utf16 pdo_drivers pear_extension_dir pear_install_dir pfsockopen pg_affected_rows pg_cancel_query pg_client_encoding pg_clientencoding pg_close pg_cmdtuples pg_connect pg_connect_poll pg_connection_busy pg_connection_reset pg_connection_status pg_consume_input pg_convert pg_copy_from pg_copy_to pg_dbname pg_delete pg_end_copy pg_errormessage pg_escape_bytea pg_escape_identifier pg_escape_literal pg_escape_string pg_exec pg_execute pg_fetch_all pg_fetch_all_columns pg_fetch_array pg_fetch_assoc pg_fetch_object pg_fetch_result pg_fetch_row pg_field_is_null pg_field_name pg_field_num pg_field_prtlen pg_field_size pg_field_table pg_field_type pg_field_type_oid pg_fieldisnull pg_fieldname pg_fieldnum pg_fieldprtlen pg_fieldsize pg_fieldtype pg_flush pg_free_result pg_freeresult pg_get_notify pg_get_pid pg_get_result pg_getlastoid pg_host pg_insert pg_last_error pg_last_notice pg_last_oid pg_lo_close pg_lo_create pg_lo_export pg_lo_import pg_lo_open pg_lo_read pg_lo_read_all pg_lo_seek pg_lo_tell pg_lo_truncate pg_lo_unlink pg_lo_write pg_loclose pg_locreate pg_loexport pg_loimport pg_loopen pg_loread pg_loreadall pg_lounlink pg_lowrite pg_meta_data pg_num_fields pg_num_rows pg_numfields pg_numrows pg_options pg_parameter_status pg_pconnect pg_ping pg_port pg_prepare pg_put_line pg_query pg_query_params pg_result pg_result_error pg_result_error_field pg_result_seek pg_result_status pg_select pg_send_execute pg_send_prepare pg_send_query pg_send_query_params pg_set_client_encoding pg_set_error_verbosity pg_setclientencoding pg_socket pg_trace pg_transaction_status pg_tty pg_unescape_bytea pg_untrace pg_update pg_version pgsql_assoc pgsql_bad_response pgsql_both pgsql_command_ok pgsql_connect_async pgsql_connect_force_new pgsql_connection_auth_ok pgsql_connection_awaiting_response pgsql_connection_bad pgsql_connection_made pgsql_connection_ok pgsql_connection_setenv pgsql_connection_started pgsql_conv_force_null pgsql_conv_ignore_default pgsql_conv_ignore_not_null pgsql_copy_in pgsql_copy_out pgsql_diag_context pgsql_diag_internal_position pgsql_diag_internal_query pgsql_diag_message_detail pgsql_diag_message_hint pgsql_diag_message_primary pgsql_diag_severity pgsql_diag_source_file pgsql_diag_source_function pgsql_diag_source_line pgsql_diag_sqlstate pgsql_diag_statement_position pgsql_dml_async pgsql_dml_escape pgsql_dml_exec pgsql_dml_no_conv pgsql_dml_string pgsql_empty_query pgsql_errors_default pgsql_errors_terse pgsql_errors_verbose pgsql_fatal_error pgsql_libpq_version pgsql_libpq_version_str pgsql_nonfatal_error pgsql_num pgsql_polling_active pgsql_polling_failed pgsql_polling_ok pgsql_polling_reading pgsql_polling_writing pgsql_seek_cur pgsql_seek_end pgsql_seek_set pgsql_status_long pgsql_status_string pgsql_transaction_active pgsql_transaction_idle pgsql_transaction_inerror pgsql_transaction_intrans pgsql_transaction_unknown pgsql_tuples_ok php_binary php_binary_read php_bindir php_check_syntax php_config_file_path php_config_file_scan_dir php_datadir php_debug php_egg_logo_guid php_eol php_extension_dir php_extra_version php_ini_loaded_file php_ini_scanned_files php_int_max php_int_size php_libdir php_localstatedir php_logo_guid php_major_version php_mandir php_maxpathlen php_minor_version php_normal_read php_os php_output_handler_clean php_output_handler_cleanable php_output_handler_cont php_output_handler_disabled php_output_handler_end php_output_handler_final php_output_handler_flush php_output_handler_flushable php_output_handler_removable php_output_handler_start php_output_handler_started php_output_handler_stdflags php_output_handler_write php_prefix php_query_rfc1738 php_query_rfc3986 php_real_logo_guid php_release_version php_round_half_down php_round_half_even php_round_half_odd php_round_half_up php_sapi php_sapi_name php_session_active php_session_disabled php_session_none php_shlib_suffix php_strip_whitespace php_svn_auth_param_ignore_ssl_verify_errors php_sysconfdir php_uname php_url_fragment php_url_host php_url_pass php_url_path php_url_port php_url_query php_url_scheme php_url_user php_version php_version_id php_windows_nt_domain_controller php_windows_nt_server php_windows_nt_workstation php_windows_version_build php_windows_version_major php_windows_version_minor php_windows_version_platform php_windows_version_producttype php_windows_version_sp_major php_windows_version_sp_minor php_windows_version_suitemask php_zts phpcredits phpinfo phpversion pi pkcs7_binary pkcs7_detached pkcs7_noattr pkcs7_nocerts pkcs7_nochain pkcs7_nointern pkcs7_nosigs pkcs7_noverify pkcs7_text pm_str png2wbmp png_all_filters png_filter_avg png_filter_none png_filter_paeth png_filter_sub png_filter_up png_no_filter poll_err poll_hup poll_in poll_msg poll_out poll_pri popen pos positive_sign posix_access posix_ctermid posix_errno posix_f_ok posix_get_last_error posix_getcwd posix_getegid posix_geteuid posix_getgid posix_getgrgid posix_getgrnam posix_getgroups posix_getlogin posix_getpgid posix_getpgrp posix_getpid posix_getppid posix_getpwnam posix_getpwuid posix_getrlimit posix_getsid posix_getuid posix_initgroups posix_isatty posix_kill posix_mkfifo posix_mknod posix_r_ok posix_s_ifblk posix_s_ifchr posix_s_ififo posix_s_ifreg posix_s_ifsock posix_setegid posix_seteuid posix_setgid posix_setpgid posix_setrlimit posix_setsid posix_setuid posix_strerror posix_times posix_ttyname posix_uname posix_w_ok posix_x_ok pow preg_backtrack_limit_error preg_bad_utf8_error preg_bad_utf8_offset_error preg_filter preg_grep preg_grep_invert preg_internal_error preg_last_error preg_match preg_match_all preg_no_error preg_offset_capture preg_pattern_order preg_quote preg_recursion_limit_error preg_replace preg_replace_callback preg_replace_callback_array preg_set_order preg_split preg_split_delim_capture preg_split_no_empty preg_split_offset_capture prev print print_r printf private proc_close proc_get_status proc_nice proc_open proc_terminate prof_trace property_exists protected ps_add_bookmark ps_add_launchlink ps_add_locallink ps_add_note ps_add_pdflink ps_add_weblink ps_arc ps_arcn ps_begin_page ps_begin_pattern ps_begin_template ps_circle ps_clip ps_close ps_close_image ps_closepath ps_closepath_stroke ps_continue_text ps_curveto ps_delete ps_end_page ps_end_pattern ps_end_template ps_fill ps_fill_stroke ps_findfont ps_get_buffer ps_get_parameter ps_get_value ps_hyphenate ps_include_file ps_linecap_butt ps_linecap_round ps_linecap_squared ps_linejoin_bevel ps_linejoin_miter ps_linejoin_round ps_lineto ps_makespotcolor ps_moveto ps_new ps_open_file ps_open_image ps_open_image_file ps_open_memory_image ps_place_image ps_rect ps_restore ps_rotate ps_save ps_scale ps_set_border_color ps_set_border_dash ps_set_border_style ps_set_info ps_set_parameter ps_set_text_pos ps_set_value ps_setcolor ps_setdash ps_setflat ps_setfont ps_setgray ps_setlinecap ps_setlinejoin ps_setlinewidth ps_setmiterlimit ps_setoverprintmode ps_setpolydash ps_shading ps_shading_pattern ps_shfill ps_show ps_show2 ps_show_boxed ps_show_xy ps_show_xy2 ps_string_geometry ps_stringwidth ps_stroke ps_symbol ps_symbol_name ps_symbol_width ps_translate psfs_err_fatal psfs_feed_me psfs_flag_flush_close psfs_flag_flush_inc psfs_flag_normal psfs_pass_on pspell_add_to_personal pspell_add_to_session pspell_bad_spellers pspell_check pspell_clear_session pspell_config_create pspell_config_data_dir pspell_config_dict_dir pspell_config_ignore pspell_config_mode pspell_config_personal pspell_config_repl pspell_config_runtogether pspell_config_save_repl pspell_fast pspell_new pspell_new_config pspell_new_personal pspell_normal pspell_run_together pspell_save_wordlist pspell_store_replacement pspell_suggest pthreads_allow_headers pthreads_inherit_all pthreads_inherit_classes pthreads_inherit_comments pthreads_inherit_constants pthreads_inherit_functions pthreads_inherit_includes pthreads_inherit_ini pthreads_inherit_none public putenv px_close px_create_fp px_date2string px_delete px_delete_record px_field_alpha px_field_autoinc px_field_bcd px_field_blob px_field_bytes px_field_currency px_field_date px_field_fmtmemoblob px_field_graphic px_field_logical px_field_long px_field_memoblob px_field_number px_field_ole px_field_short px_field_time px_field_timestamp px_file_inc_sec_index px_file_inc_sec_index_g px_file_index_db px_file_non_inc_sec_index px_file_non_inc_sec_index_g px_file_non_index_db px_file_prim_index px_file_sec_index px_file_sec_index_g px_get_field px_get_info px_get_parameter px_get_record px_get_schema px_get_value px_insert_record px_keytolower px_keytoupper px_new px_numfields px_numrecords px_open_fp px_put_record px_retrieve_record px_set_blob_file px_set_parameter px_set_tablename px_set_targetencoding px_set_value px_timestamp2string px_update_record quoted_printable_decode quoted_printable_encode quotemeta rad2deg radius_access_accept radius_access_challenge radius_access_reject radius_access_request radius_accounting_off radius_accounting_on radius_accounting_request radius_accounting_response radius_acct_authentic radius_acct_delay_time radius_acct_input_octets radius_acct_input_packets radius_acct_link_count radius_acct_multi_session_id radius_acct_open radius_acct_output_octets radius_acct_output_packets radius_acct_session_id radius_acct_session_time radius_acct_status_type radius_acct_terminate_cause radius_add_server radius_administrative radius_adsl_cap radius_adsl_dmt radius_arap radius_async radius_auth_local radius_auth_open radius_auth_radius radius_auth_remote radius_authenticate_only radius_cable radius_callback_framed radius_callback_id radius_callback_login radius_callback_nas_prompt radius_callback_number radius_called_station_id radius_calling_station_id radius_chap_challenge radius_chap_password radius_class radius_close radius_coa_ack radius_coa_nak radius_coa_request radius_comp_ipxhdr radius_comp_none radius_comp_stac_lzs radius_comp_vj radius_config radius_connect_info radius_create_request radius_cvt_addr radius_cvt_int radius_cvt_string radius_demangle radius_demangle_mppe_key radius_disconnect_ack radius_disconnect_nak radius_disconnect_request radius_ethernet radius_filter_id radius_framed radius_framed_appletalk_link radius_framed_appletalk_network radius_framed_appletalk_zone radius_framed_compression radius_framed_ip_address radius_framed_ip_netmask radius_framed_ipx_network radius_framed_mtu radius_framed_protocol radius_framed_route radius_framed_routing radius_g_3_fax radius_gandalf radius_get_attr radius_get_tagged_attr_data radius_get_tagged_attr_tag radius_get_vendor_attr radius_hdlc_clear_channel radius_idle_timeout radius_idsl radius_isdn_async_v110 radius_isdn_async_v120 radius_isdn_sync radius_login radius_login_ip_host radius_login_lat_group radius_login_lat_node radius_login_lat_port radius_login_lat_service radius_login_service radius_login_tcp_port radius_microsoft_ms_acct_auth_type radius_microsoft_ms_acct_eap_type radius_microsoft_ms_arap_challenge radius_microsoft_ms_arap_password_change_reason radius_microsoft_ms_bap_usage radius_microsoft_ms_chap2_pw radius_microsoft_ms_chap2_response radius_microsoft_ms_chap2_success radius_microsoft_ms_chap_challenge radius_microsoft_ms_chap_domain radius_microsoft_ms_chap_error radius_microsoft_ms_chap_lm_enc_pw radius_microsoft_ms_chap_mppe_keys radius_microsoft_ms_chap_nt_enc_pw radius_microsoft_ms_chap_pw_1 radius_microsoft_ms_chap_pw_2 radius_microsoft_ms_chap_response radius_microsoft_ms_filter radius_microsoft_ms_link_drop_time_limit radius_microsoft_ms_link_utilization_threshold radius_microsoft_ms_mppe_encryption_policy radius_microsoft_ms_mppe_encryption_types radius_microsoft_ms_mppe_recv_key radius_microsoft_ms_mppe_send_key radius_microsoft_ms_new_arap_password radius_microsoft_ms_old_arap_password radius_microsoft_ms_primary_dns_server radius_microsoft_ms_primary_nbns_server radius_microsoft_ms_ras_vendor radius_microsoft_ms_ras_version radius_microsoft_ms_secondary_dns_server radius_microsoft_ms_secondary_nbns_server radius_mppe_key_len radius_nas_identifier radius_nas_ip_address radius_nas_port radius_nas_port_type radius_nas_prompt radius_option_salt radius_option_tagged radius_outbound radius_piafs radius_port_limit radius_ppp radius_proxy_state radius_put_addr radius_put_attr radius_put_int radius_put_string radius_put_vendor_addr radius_put_vendor_attr radius_put_vendor_int radius_put_vendor_string radius_reply_message radius_request_authenticator radius_salt_encrypt_attr radius_sdsl radius_send_request radius_server_secret radius_service_type radius_session_timeout radius_slip radius_start radius_state radius_stop radius_strerror radius_sync radius_term_admin_reboot radius_term_admin_reset radius_term_callback radius_term_host_request radius_term_idle_timeout radius_term_lost_carrier radius_term_lost_service radius_term_nas_error radius_term_nas_reboot radius_term_nas_request radius_term_port_error radius_term_port_preempted radius_term_port_suspended radius_term_port_unneeded radius_term_service_unavailable radius_term_session_timeout radius_term_user_error radius_term_user_request radius_termination_action radius_user_name radius_user_password radius_vendor_microsoft radius_vendor_specific radius_virtual radius_wireless_ieee_802_11 radius_wireless_other radius_x_25 radius_x_75 radius_xdsl radius_xylogics radixchar rand random_bytes random_int range rar_host_beos rar_host_msdos rar_host_os2 rar_host_unix rar_host_win32 rar_wrapper_cache_stats rawurldecode rawurlencode read_exif_data readdir readfile readgzfile readline readline_add_history readline_callback_handler_install readline_callback_handler_remove readline_callback_read_char readline_clear_history readline_completion_function readline_info readline_list_history readline_on_new_line readline_read_history readline_redisplay readline_write_history readlink real realpath realpath_cache_get realpath_cache_size register_shutdown_function register_tick_function rename rename_function require require_once reset resource resourcebundle_count resourcebundle_create resourcebundle_get resourcebundle_get_error_code resourcebundle_get_error_message resourcebundle_locales restore_error_handler restore_exception_handler restore_include_path return rewind rewinddir rmdir round rpm_close rpm_get_tag rpm_is_valid rpm_open rpm_version rpmreader_arch rpmreader_archivesize rpmreader_basenames rpmreader_buildarchs rpmreader_buildhost rpmreader_buildtime rpmreader_cachectime rpmreader_cachepkgmtime rpmreader_cachepkgpath rpmreader_cachepkgsize rpmreader_changelogname rpmreader_changelogtext rpmreader_changelogtime rpmreader_classdict rpmreader_conflictflags rpmreader_conflictname rpmreader_conflictversion rpmreader_cookie rpmreader_copyright rpmreader_dependsdict rpmreader_description rpmreader_dirindexes rpmreader_dirnames rpmreader_distribution rpmreader_disturl rpmreader_epoch rpmreader_excludearch rpmreader_excludeos rpmreader_exclusivearch rpmreader_exclusiveos rpmreader_fileclass rpmreader_filecolors rpmreader_filecontexts rpmreader_filedependsn rpmreader_filedependsx rpmreader_filedevices rpmreader_fileflags rpmreader_filegroupname rpmreader_fileinodes rpmreader_filelangs rpmreader_filelinktos rpmreader_filemd5s rpmreader_filemodes rpmreader_filemtimes rpmreader_filerdevs rpmreader_filesizes rpmreader_filestates rpmreader_fileusername rpmreader_fileverifyflags rpmreader_fscontexts rpmreader_gif rpmreader_group rpmreader_icon rpmreader_installcolor rpmreader_installtid rpmreader_installtime rpmreader_instprefixes rpmreader_license rpmreader_maximum rpmreader_minimum rpmreader_name rpmreader_obsoleteflags rpmreader_obsoletename rpmreader_obsoletes rpmreader_obsoleteversion rpmreader_oldfilenames rpmreader_optflags rpmreader_os rpmreader_packager rpmreader_patch rpmreader_patchesflags rpmreader_patchesname rpmreader_patchesversion rpmreader_payloadcompressor rpmreader_payloadflags rpmreader_payloadformat rpmreader_platform rpmreader_policies rpmreader_postin rpmreader_postinprog rpmreader_postun rpmreader_postunprog rpmreader_prefixes rpmreader_prein rpmreader_preinprog rpmreader_preun rpmreader_preunprog rpmreader_provideflags rpmreader_providename rpmreader_provides rpmreader_provideversion rpmreader_recontexts rpmreader_release rpmreader_removetid rpmreader_requireflags rpmreader_requirename rpmreader_requireversion rpmreader_rhnplatform rpmreader_rpmversion rpmreader_serial rpmreader_size rpmreader_source rpmreader_sourcepkgid rpmreader_sourcerpm rpmreader_summary rpmreader_triggerflags rpmreader_triggerindex rpmreader_triggername rpmreader_triggerscriptprog rpmreader_triggerscripts rpmreader_triggerversion rpmreader_url rpmreader_vendor rpmreader_verifyscript rpmreader_verifyscriptprog rpmreader_version rpmreader_xpm rsort rtrim s_all s_executor s_files s_include s_internal s_irgrp s_iroth s_irusr s_irwxg s_irwxo s_irwxu s_iwgrp s_iwoth s_iwusr s_ixgrp s_ixoth s_ixusr s_mail s_memory s_misc s_session s_sql s_vars sa_all sa_messages sa_recent sa_uidnext sa_uidvalidity sa_unseen scandir scandir_sort_ascending scandir_sort_descending scandir_sort_none se_free se_noprefetch se_uid seek_cur seek_end seek_set segv_accerr segv_maperr sem_acquire sem_get sem_release sem_remove serialize session_abort session_cache_expire session_cache_limiter session_commit session_decode session_destroy session_encode session_get_cookie_params session_id session_is_registered session_module_name session_name session_pgsql_add_error session_pgsql_get_error session_pgsql_get_field session_pgsql_reset session_pgsql_set_field session_pgsql_status session_regenerate_id session_register session_register_shutdown session_reset session_save_path session_set_cookie_params session_set_save_handler session_start session_status session_unregister session_unset session_write_close set_error_handler set_exception_handler set_file_buffer set_include_path set_magic_quotes_runtime set_socket_blocking set_time_limit setcookie setlocale setproctitle setrawcookie setthreadtitle settype sha1 sha1_file shell_exec shm_attach shm_detach shm_get_var shm_has_var shm_put_var shm_remove shm_remove_var shmop_close shmop_delete shmop_open shmop_read shmop_size shmop_write show_source shuffle si_asyncio si_kernel si_msggq si_noinfo si_queue si_sigio si_timer si_tkill si_user sid sig_block sig_dfl sig_err sig_ign sig_setmask sig_unblock sigabrt sigalrm sigbaby sigbus sigchld sigcld sigcont sigfpe sighup sigill sigint sigio sigiot sigkill signeurlpaiement sigpipe sigpoll sigprof sigpwr sigquit sigsegv sigstkflt sigstop sigsys sigterm sigtrap sigtstp sigttin sigttou sigurg sigusr1 sigusr2 sigvtalrm sigwinch sigxcpu sigxfsz similar_text simplexml_import_dom simplexml_load_file simplexml_load_string sin sinh sizeof sleep snmp2_get snmp2_getnext snmp2_real_walk snmp2_set snmp2_walk snmp3_get snmp3_getnext snmp3_real_walk snmp3_set snmp3_walk snmp_bit_str snmp_counter snmp_counter64 snmp_get_quick_print snmp_get_valueretrieval snmp_integer snmp_ipaddress snmp_null snmp_object_id snmp_octet_str snmp_oid_output_full snmp_oid_output_module snmp_oid_output_none snmp_oid_output_numeric snmp_oid_output_suffix snmp_oid_output_ucd snmp_opaque snmp_read_mib snmp_set_enum_print snmp_set_oid_numeric_print snmp_set_oid_output_format snmp_set_quick_print snmp_set_valueretrieval snmp_timeticks snmp_uinteger snmp_unsigned snmp_value_library snmp_value_object snmp_value_plain snmpget snmpgetnext snmprealwalk snmpset snmpwalk snmpwalkoid so_bindtodevice so_broadcast so_debug so_dontroute so_error so_free so_keepalive so_linger so_noserver so_oobinline so_rcvbuf so_rcvlowat so_rcvtimeo so_reuseaddr so_reuseport so_sndbuf so_sndlowat so_sndtimeo so_type soap_1_1 soap_1_2 soap_actor_next soap_actor_none soap_actor_unlimatereceiver soap_authentication_basic soap_authentication_digest soap_compression_accept soap_compression_deflate soap_compression_gzip soap_document soap_enc_array soap_enc_object soap_encoded soap_functions_all soap_literal soap_persistence_request soap_persistence_session soap_rpc soap_single_element_arrays soap_ssl_method_sslv2 soap_ssl_method_sslv23 soap_ssl_method_sslv3 soap_ssl_method_tls soap_use_xsi_array_type soap_wait_one_way_calls sock_dgram sock_raw sock_rdm sock_seqpacket sock_stream socket_accept socket_addrinuse socket_bind socket_clear_error socket_close socket_cmsg_space socket_connect socket_create socket_create_listen socket_create_pair socket_e2big socket_eacces socket_eaddrinuse socket_eaddrnotavail socket_eadv socket_eafnosupport socket_eagain socket_ealready socket_ebade socket_ebadf socket_ebadfd socket_ebadmsg socket_ebadr socket_ebadrqc socket_ebadslt socket_ebusy socket_echrng socket_ecomm socket_econnaborted socket_econnrefused socket_econnreset socket_edestaddrreq socket_ediscon socket_edquot socket_eduot socket_eexist socket_efault socket_ehostdown socket_ehostunreach socket_eidrm socket_einprogress socket_eintr socket_einval socket_eio socket_eisconn socket_eisdir socket_eisnam socket_el2hlt socket_el2nsync socket_el3hlt socket_el3rst socket_elnrng socket_eloop socket_emediumtype socket_emfile socket_emlink socket_emsgsize socket_emultihop socket_enametoolong socket_enetdown socket_enetreset socket_enetunreach socket_enfile socket_enoano socket_enobufs socket_enocsi socket_enodata socket_enodev socket_enoent socket_enolck socket_enolink socket_enomedium socket_enomem socket_enomsg socket_enonet socket_enoprotoopt socket_enospc socket_enosr socket_enostr socket_enosys socket_enotblk socket_enotconn socket_enotdir socket_enotempty socket_enotsock socket_enotty socket_enotuniq socket_enxio socket_eopnotsupp socket_eperm socket_epfnosupport socket_epipe socket_eproclim socket_eproto socket_eprotonosupport socket_eprotoopt socket_eprototype socket_eremchg socket_eremote socket_eremoteio socket_erestart socket_erofs socket_eshutdown socket_esocktnosupport socket_espipe socket_esrmnt socket_estale socket_estrpipe socket_etime socket_etimedout socket_etoomanyrefs socket_etoomyrefs socket_eunatch socket_eusers socket_ewouldblock socket_exdev socket_exfull socket_get_option socket_get_status socket_getopt socket_getpeername socket_getsockname socket_host_not_found socket_import_stream socket_last_error socket_listen socket_no_address socket_no_data socket_no_recovery socket_notinitialised socket_read socket_recv socket_recvfrom socket_recvmsg socket_select socket_send socket_sendmsg socket_sendto socket_set_block socket_set_blocking socket_set_nonblock socket_set_option socket_set_timeout socket_setopt socket_shutdown socket_strerror socket_sysnotready socket_try_again socket_vernotsupported socket_write sol_socket sol_tcp sol_udp somaxconn sort sort_asc sort_desc sort_flag_case sort_locale_string sort_natural sort_numeric sort_regular sort_string sortarrival sortcc sortdate sortfrom sortsize sortsubject sortto soundex spl_autoload spl_autoload_call spl_autoload_extensions spl_autoload_functions spl_autoload_register spl_autoload_unregister spl_classes spl_object_hash split spliti sprintf sql_best_rowid sql_bigint sql_binary sql_bit sql_char sql_concur_lock sql_concur_read_only sql_concur_rowver sql_concur_values sql_concurrency sql_cur_use_driver sql_cur_use_if_needed sql_cur_use_odbc sql_cursor_dynamic sql_cursor_forward_only sql_cursor_keyset_driven sql_cursor_static sql_cursor_type sql_date sql_decimal sql_double sql_ensure sql_fetch_first sql_fetch_next sql_float sql_index_all sql_index_unique sql_integer sql_keyset_size sql_longvarbinary sql_longvarchar sql_no_nulls sql_nullable sql_numeric sql_odbc_cursors sql_quick sql_real sql_regcase sql_rowver sql_scope_currow sql_scope_session sql_scope_transaction sql_smallint sql_time sql_timestamp sql_tinyint sql_type_date sql_type_time sql_type_timestamp sql_varbinary sql_varchar sql_wchar sql_wlongvarchar sql_wvarchar sqlbit sqlchar sqlflt4 sqlflt8 sqlint1 sqlint2 sqlint4 sqlite3_assoc sqlite3_blob sqlite3_both sqlite3_float sqlite3_integer sqlite3_null sqlite3_num sqlite3_open_create sqlite3_open_readonly sqlite3_open_readwrite sqlite3_text sqlite_abort sqlite_array_query sqlite_assoc sqlite_auth sqlite_both sqlite_busy sqlite_busy_timeout sqlite_cantopen sqlite_changes sqlite_close sqlite_column sqlite_constraint sqlite_corrupt sqlite_create_aggregate sqlite_create_function sqlite_current sqlite_done sqlite_empty sqlite_error sqlite_error_string sqlite_escape_string sqlite_exec sqlite_factory sqlite_fetch_all sqlite_fetch_array sqlite_fetch_column_types sqlite_fetch_object sqlite_fetch_single sqlite_fetch_string sqlite_field_name sqlite_format sqlite_full sqlite_has_more sqlite_has_prev sqlite_internal sqlite_interrupt sqlite_ioerr sqlite_key sqlite_last_error sqlite_last_insert_rowid sqlite_libencoding sqlite_libversion sqlite_locked sqlite_mismatch sqlite_misuse sqlite_next sqlite_nolfs sqlite_nomem sqlite_notadb sqlite_notfound sqlite_num sqlite_num_fields sqlite_num_rows sqlite_ok sqlite_open sqlite_perm sqlite_popen sqlite_prev sqlite_protocol sqlite_query sqlite_readonly sqlite_rewind sqlite_row sqlite_schema sqlite_seek sqlite_single_query sqlite_toobig sqlite_udf_decode_binary sqlite_udf_encode_binary sqlite_unbuffered_query sqlite_valid sqlsrv_begin_transaction sqlsrv_cancel sqlsrv_client_info sqlsrv_close sqlsrv_commit sqlsrv_configure sqlsrv_connect sqlsrv_cursor_buffered sqlsrv_cursor_dynamic sqlsrv_cursor_forward sqlsrv_cursor_keyset sqlsrv_cursor_static sqlsrv_enc_binary sqlsrv_enc_char sqlsrv_err_all sqlsrv_err_errors sqlsrv_err_warnings sqlsrv_errors sqlsrv_execute sqlsrv_fetch sqlsrv_fetch_array sqlsrv_fetch_assoc sqlsrv_fetch_both sqlsrv_fetch_numeric sqlsrv_fetch_object sqlsrv_field_metadata sqlsrv_free_stmt sqlsrv_get_config sqlsrv_get_field sqlsrv_has_rows sqlsrv_log_severity_all sqlsrv_log_severity_error sqlsrv_log_severity_notice sqlsrv_log_severity_warning sqlsrv_log_system_all sqlsrv_log_system_conn sqlsrv_log_system_init sqlsrv_log_system_off sqlsrv_log_system_stmt sqlsrv_log_system_util sqlsrv_next_result sqlsrv_nullable_no sqlsrv_nullable_unknown sqlsrv_nullable_yes sqlsrv_num_fields sqlsrv_num_rows sqlsrv_param_in sqlsrv_param_inout sqlsrv_param_out sqlsrv_phptype_datetime sqlsrv_phptype_float sqlsrv_phptype_int sqlsrv_phptype_null sqlsrv_phptype_stream sqlsrv_phptype_string sqlsrv_prepare sqlsrv_query sqlsrv_rollback sqlsrv_rows_affected sqlsrv_scroll_absolute sqlsrv_scroll_first sqlsrv_scroll_last sqlsrv_scroll_next sqlsrv_scroll_prior sqlsrv_scroll_relative sqlsrv_send_stream_data sqlsrv_server_info sqlsrv_sqltype_bigint sqlsrv_sqltype_binary sqlsrv_sqltype_bit sqlsrv_sqltype_char sqlsrv_sqltype_date sqlsrv_sqltype_datetime sqlsrv_sqltype_datetime2 sqlsrv_sqltype_datetimeoffset sqlsrv_sqltype_decimal sqlsrv_sqltype_float sqlsrv_sqltype_image sqlsrv_sqltype_int sqlsrv_sqltype_money sqlsrv_sqltype_nchar sqlsrv_sqltype_ntext sqlsrv_sqltype_numeric sqlsrv_sqltype_nvarchar sqlsrv_sqltype_real sqlsrv_sqltype_smalldatetime sqlsrv_sqltype_smallint sqlsrv_sqltype_smallmoney sqlsrv_sqltype_text sqlsrv_sqltype_time sqlsrv_sqltype_timestamp sqlsrv_sqltype_tinyint sqlsrv_sqltype_udt sqlsrv_sqltype_uniqueidentifier sqlsrv_sqltype_varbinary sqlsrv_sqltype_varchar sqlsrv_sqltype_xml sqlsrv_txn_read_committed sqlsrv_txn_read_serializable sqlsrv_txn_read_uncommitted sqlsrv_txn_repeatable_read sqlsrv_txn_serializable sqlsrv_txn_snapshot sqlt_afc sqlt_avc sqlt_bdouble sqlt_bfilee sqlt_bfloat sqlt_bin sqlt_blob sqlt_bol sqlt_cfilee sqlt_chr sqlt_clob sqlt_flt sqlt_int sqlt_lbi sqlt_lng sqlt_lvc sqlt_nty sqlt_num sqlt_odt sqlt_rdd sqlt_rset sqlt_str sqlt_uin sqlt_vcs sqltext sqlvarchar sqrt srand sscanf ssdeep_fuzzy_compare ssdeep_fuzzy_hash ssdeep_fuzzy_hash_filename ssh2_auth_agent ssh2_auth_hostbased_file ssh2_auth_none ssh2_auth_password ssh2_auth_pubkey_file ssh2_connect ssh2_default_term_height ssh2_default_term_unit ssh2_default_term_width ssh2_default_terminal ssh2_exec ssh2_fetch_stream ssh2_fingerprint ssh2_fingerprint_hex ssh2_fingerprint_md5 ssh2_fingerprint_raw ssh2_fingerprint_sha1 ssh2_methods_negotiated ssh2_publickey_add ssh2_publickey_init ssh2_publickey_list ssh2_publickey_remove ssh2_scp_recv ssh2_scp_send ssh2_sftp ssh2_sftp_chmod ssh2_sftp_lstat ssh2_sftp_mkdir ssh2_sftp_readlink ssh2_sftp_realpath ssh2_sftp_rename ssh2_sftp_rmdir ssh2_sftp_stat ssh2_sftp_symlink ssh2_sftp_unlink ssh2_shell ssh2_stream_stderr ssh2_stream_stdio ssh2_term_unit_chars ssh2_term_unit_pixels ssh2_tunnel st_set st_silent st_uid stat statement_trace static stats_absolute_deviation stats_cdf_beta stats_cdf_binomial stats_cdf_cauchy stats_cdf_chisquare stats_cdf_exponential stats_cdf_f stats_cdf_gamma stats_cdf_laplace stats_cdf_logistic stats_cdf_negative_binomial stats_cdf_noncentral_chisquare stats_cdf_noncentral_f stats_cdf_poisson stats_cdf_t stats_cdf_uniform stats_cdf_weibull stats_covariance stats_den_uniform stats_dens_beta stats_dens_cauchy stats_dens_chisquare stats_dens_exponential stats_dens_f stats_dens_gamma stats_dens_laplace stats_dens_logistic stats_dens_negative_binomial stats_dens_normal stats_dens_pmf_binomial stats_dens_pmf_hypergeometric stats_dens_pmf_poisson stats_dens_t stats_dens_weibull stats_harmonic_mean stats_kurtosis stats_rand_gen_beta stats_rand_gen_chisquare stats_rand_gen_exponential stats_rand_gen_f stats_rand_gen_funiform stats_rand_gen_gamma stats_rand_gen_ibinomial stats_rand_gen_ibinomial_negative stats_rand_gen_int stats_rand_gen_ipoisson stats_rand_gen_iuniform stats_rand_gen_noncenral_chisquare stats_rand_gen_noncentral_f stats_rand_gen_noncentral_t stats_rand_gen_normal stats_rand_gen_t stats_rand_get_seeds stats_rand_phrase_to_seeds stats_rand_ranf stats_rand_setall stats_skew stats_standard_deviation stats_stat_binomial_coef stats_stat_correlation stats_stat_gennch stats_stat_independent_t stats_stat_innerproduct stats_stat_noncentral_t stats_stat_paired_t stats_stat_percentile stats_stat_powersum stats_variance stdclass str_getcsv str_ireplace str_pad str_pad_both str_pad_left str_pad_right str_repeat str_replace str_rot13 str_shuffle str_split str_word_count strcasecmp strchr strcmp strcoll strcspn stream_bucket_append stream_bucket_make_writeable stream_bucket_new stream_bucket_prepend stream_buffer_full stream_buffer_line stream_buffer_none stream_cast_as_stream stream_cast_for_select stream_client_async_connect stream_client_connect stream_client_persistent stream_context_create stream_context_get_default stream_context_get_options stream_context_get_params stream_context_set_default stream_context_set_option stream_context_set_params stream_copy_to_stream stream_crypto_method_any_client stream_crypto_method_any_server stream_crypto_method_sslv23_client stream_crypto_method_sslv23_server stream_crypto_method_sslv2_client stream_crypto_method_sslv2_server stream_crypto_method_sslv3_client stream_crypto_method_sslv3_server stream_crypto_method_tls_client stream_crypto_method_tls_server stream_crypto_method_tlsv1_0_client stream_crypto_method_tlsv1_0_server stream_crypto_method_tlsv1_1_client stream_crypto_method_tlsv1_1_server stream_crypto_method_tlsv1_2_client stream_crypto_method_tlsv1_2_server stream_encoding stream_enforce_safe_mode stream_filter_all stream_filter_append stream_filter_prepend stream_filter_read stream_filter_register stream_filter_remove stream_filter_write stream_get_contents stream_get_filters stream_get_line stream_get_meta_data stream_get_transports stream_get_wrappers stream_ignore_url stream_ipproto_icmp stream_ipproto_ip stream_ipproto_raw stream_ipproto_tcp stream_ipproto_udp stream_is_local stream_is_url stream_meta_access stream_meta_group stream_meta_group_name stream_meta_owner stream_meta_owner_name stream_meta_touch stream_mkdir_recursive stream_must_seek stream_notification_callback stream_notify_auth_required stream_notify_auth_result stream_notify_completed stream_notify_connect stream_notify_failure stream_notify_file_size_is stream_notify_mime_type_is stream_notify_progress stream_notify_redirected stream_notify_resolve stream_notify_severity_err stream_notify_severity_info stream_notify_severity_warn stream_oob stream_option_blocking stream_option_read_buffer stream_option_read_timeout stream_option_write_buffer stream_peek stream_pf_inet stream_pf_inet6 stream_pf_unix stream_register_wrapper stream_report_errors stream_resolve_include_path stream_select stream_server_bind stream_server_listen stream_set_blocking stream_set_chunk_size stream_set_read_buffer stream_set_timeout stream_set_write_buffer stream_shut_rd stream_shut_rdwr stream_shut_wr stream_sock_dgram stream_sock_raw stream_sock_rdm stream_sock_seqpacket stream_sock_stream stream_socket_accept stream_socket_client stream_socket_enable_crypto stream_socket_get_name stream_socket_pair stream_socket_recvfrom stream_socket_sendto stream_socket_server stream_socket_shutdown stream_supports_lock stream_url_stat_link stream_url_stat_quiet stream_use_path stream_wrapper_register stream_wrapper_restore stream_wrapper_unregister strftime string strip_tags stripcslashes stripos stripslashes stristr strlen strnatcasecmp strnatcmp strncasecmp strncmp strpbrk strpos strptime strrchr strrev strripos strrpos strspn strstr strtok strtolower strtotime strtoupper strtr strval substr substr_compare substr_count substr_replace suhosin_patch suhosin_patch_version summary_trace sunfuncs_ret_double sunfuncs_ret_string sunfuncs_ret_timestamp svn_add svn_auth_get_parameter svn_auth_param_config svn_auth_param_config_dir svn_auth_param_default_password svn_auth_param_default_username svn_auth_param_dont_store_passwords svn_auth_param_no_auth_cache svn_auth_param_non_interactive svn_auth_param_server_group svn_auth_param_ssl_server_cert_info svn_auth_param_ssl_server_failures svn_auth_set_parameter svn_blame svn_cat svn_checkout svn_cleanup svn_client_version svn_commit svn_delete svn_diff svn_export svn_fs_abort_txn svn_fs_apply_text svn_fs_begin_txn2 svn_fs_change_node_prop svn_fs_check_path svn_fs_config_fs_type svn_fs_contents_changed svn_fs_copy svn_fs_delete svn_fs_dir_entries svn_fs_file_contents svn_fs_file_length svn_fs_is_dir svn_fs_is_file svn_fs_make_dir svn_fs_make_file svn_fs_node_created_rev svn_fs_node_prop svn_fs_props_changed svn_fs_revision_prop svn_fs_revision_root svn_fs_txn_root svn_fs_type_bdb svn_fs_type_fsfs svn_fs_youngest_rev svn_import svn_log svn_ls svn_mkdir svn_node_dir svn_node_file svn_node_none svn_node_unknown svn_prop_revision_author svn_prop_revision_date svn_prop_revision_log svn_prop_revision_orig_date svn_repos_create svn_repos_fs svn_repos_fs_begin_txn_for_commit svn_repos_fs_commit_txn svn_repos_hotcopy svn_repos_open svn_repos_recover svn_revert svn_revision_head svn_status svn_update svn_wc_status_added svn_wc_status_conflicted svn_wc_status_deleted svn_wc_status_external svn_wc_status_ignored svn_wc_status_incomplete svn_wc_status_merged svn_wc_status_missing svn_wc_status_modified svn_wc_status_none svn_wc_status_normal svn_wc_status_obstructed svn_wc_status_replaced svn_wc_status_unversioned swfaction_data swfaction_enterframe swfaction_keydown swfaction_keyup swfaction_mousedown swfaction_mousemove swfaction_mouseup swfaction_onload swfaction_unload swfbutton_down swfbutton_dragout swfbutton_dragover swfbutton_hit swfbutton_mousedown swfbutton_mouseout swfbutton_mouseover swfbutton_mouseup swfbutton_mouseupoutside swfbutton_over swfbutton_up swffill_clipped_bitmap swffill_linear_gradient swffill_radial_gradient swffill_tiled_bitmap swftextfield_align_center swftextfield_align_justify swftextfield_align_left swftextfield_align_right swftextfield_drawbox swftextfield_haslength swftextfield_html swftextfield_multiline swftextfield_noedit swftextfield_noselect swftextfield_password swftextfield_wordwrap switch sybase_affected_rows sybase_close sybase_connect sybase_data_seek sybase_deadlock_retry_count sybase_fetch_array sybase_fetch_assoc sybase_fetch_field sybase_fetch_object sybase_fetch_row sybase_field_seek sybase_free_result sybase_get_last_message sybase_min_client_severity sybase_min_error_severity sybase_min_message_severity sybase_min_server_severity sybase_num_fields sybase_num_rows sybase_pconnect sybase_query sybase_result sybase_select_db sybase_set_message_handler sybase_unbuffered_query symlink sys_get_temp_dir sys_getloadavg syslog system t_abstract t_and_equal t_array t_array_cast t_as t_bad_character t_bool_cast t_boolean_and t_boolean_or t_break t_callable t_case t_catch t_character t_class t_class_c t_clone t_close_tag t_comment t_concat_equal t_const t_constant_encapsed_string t_continue t_curly_open t_dec t_declare t_default t_dir t_div_equal t_dnumber t_do t_doc_comment t_dollar_open_curly_braces t_double_arrow t_double_cast t_double_colon t_echo t_ellipsis t_else t_elseif t_empty t_encapsed_and_whitespace t_end_heredoc t_enddeclare t_endfor t_endforeach t_endif t_endswitch t_endwhile t_eval t_exit t_extends t_file t_final t_finally t_fmt t_fmt_ampm t_for t_foreach t_func_c t_function t_global t_goto t_halt_compiler t_if t_implements t_inc t_include t_include_once t_inline_html t_instanceof t_insteadof t_int_cast t_interface t_is_equal t_is_greater_or_equal t_is_identical t_is_not_equal t_is_not_identical t_is_smaller_or_equal t_isset t_line t_list t_lnumber t_logical_and t_logical_or t_logical_xor t_method_c t_minus_equal t_mod_equal t_mul_equal t_namespace t_new t_ns_c t_ns_separator t_num_string t_object_cast t_object_operator t_open_tag t_open_tag_with_echo t_or_equal t_paamayim_nekudotayim t_plus_equal t_pow t_pow_equal t_print t_private t_protected t_public t_require t_require_once t_return t_sl t_sl_equal t_sr t_sr_equal t_start_heredoc t_static t_string t_string_cast t_string_varname t_switch t_throw t_trait t_trait_c t_try t_unset t_unset_cast t_use t_var t_variable t_while t_whitespace t_xor_equal t_yield taint tan tanh tcp_nodelay tcpwrap_check tempnam textdomain thousands_sep thousep throw tidy_access_count tidy_clean_repair tidy_config_count tidy_diagnose tidy_error_count tidy_get_body tidy_get_config tidy_get_error_buffer tidy_get_head tidy_get_html tidy_get_html_ver tidy_get_output tidy_get_release tidy_get_root tidy_get_status tidy_getopt tidy_is_xhtml tidy_is_xml tidy_load_config tidy_nodetype_asp tidy_nodetype_cdata tidy_nodetype_comment tidy_nodetype_doctype tidy_nodetype_end tidy_nodetype_jste tidy_nodetype_php tidy_nodetype_procins tidy_nodetype_root tidy_nodetype_section tidy_nodetype_start tidy_nodetype_startend tidy_nodetype_text tidy_nodetype_xmldecl tidy_parse_file tidy_parse_string tidy_repair_file tidy_repair_string tidy_reset_config tidy_save_config tidy_set_encoding tidy_setopt tidy_tag_a tidy_tag_abbr tidy_tag_acronym tidy_tag_address tidy_tag_align tidy_tag_applet tidy_tag_area tidy_tag_b tidy_tag_base tidy_tag_basefont tidy_tag_bdo tidy_tag_bgsound tidy_tag_big tidy_tag_blink tidy_tag_blockquote tidy_tag_body tidy_tag_br tidy_tag_button tidy_tag_caption tidy_tag_center tidy_tag_cite tidy_tag_code tidy_tag_col tidy_tag_colgroup tidy_tag_comment tidy_tag_dd tidy_tag_del tidy_tag_dfn tidy_tag_dir tidy_tag_div tidy_tag_dl tidy_tag_dt tidy_tag_em tidy_tag_embed tidy_tag_fieldset tidy_tag_font tidy_tag_form tidy_tag_frame tidy_tag_frameset tidy_tag_h1 tidy_tag_h2 tidy_tag_h3 tidy_tag_h4 tidy_tag_h5 tidy_tag_h6 tidy_tag_head tidy_tag_hr tidy_tag_html tidy_tag_i tidy_tag_iframe tidy_tag_ilayer tidy_tag_img tidy_tag_input tidy_tag_ins tidy_tag_isindex tidy_tag_kbd tidy_tag_keygen tidy_tag_label tidy_tag_layer tidy_tag_legend tidy_tag_li tidy_tag_link tidy_tag_listing tidy_tag_map tidy_tag_marquee tidy_tag_menu tidy_tag_meta tidy_tag_multicol tidy_tag_nobr tidy_tag_noembed tidy_tag_noframes tidy_tag_nolayer tidy_tag_nosave tidy_tag_noscript tidy_tag_object tidy_tag_ol tidy_tag_optgroup tidy_tag_option tidy_tag_p tidy_tag_param tidy_tag_plaintext tidy_tag_pre tidy_tag_q tidy_tag_rb tidy_tag_rbc tidy_tag_rp tidy_tag_rt tidy_tag_rtc tidy_tag_ruby tidy_tag_s tidy_tag_samp tidy_tag_script tidy_tag_select tidy_tag_server tidy_tag_servlet tidy_tag_small tidy_tag_spacer tidy_tag_span tidy_tag_strike tidy_tag_strong tidy_tag_style tidy_tag_sub tidy_tag_sup tidy_tag_table tidy_tag_tbody tidy_tag_td tidy_tag_textarea tidy_tag_tfoot tidy_tag_th tidy_tag_thead tidy_tag_title tidy_tag_tr tidy_tag_tt tidy_tag_u tidy_tag_ul tidy_tag_unknown tidy_tag_var tidy_tag_wbr tidy_tag_xmp tidy_warning_count time time_nanosleep time_sleep_until timezone_abbreviations_list timezone_identifiers_list timezone_location_get timezone_name_from_abbr timezone_name_get timezone_offset_get timezone_open timezone_transitions_get timezone_version_get timing_trace tmpfile token_get_all token_name touch trader_acos trader_ad trader_add trader_adosc trader_adx trader_adxr trader_apo trader_aroon trader_aroonosc trader_asin trader_atan trader_atr trader_avgprice trader_bbands trader_beta trader_bop trader_cci trader_cdl2crows trader_cdl3blackcrows trader_cdl3inside trader_cdl3linestrike trader_cdl3outside trader_cdl3starsinsouth trader_cdl3whitesoldiers trader_cdlabandonedbaby trader_cdladvanceblock trader_cdlbelthold trader_cdlbreakaway trader_cdlclosingmarubozu trader_cdlconcealbabyswall trader_cdlcounterattack trader_cdldarkcloudcover trader_cdldoji trader_cdldojistar trader_cdldragonflydoji trader_cdlengulfing trader_cdleveningdojistar trader_cdleveningstar trader_cdlgapsidesidewhite trader_cdlgravestonedoji trader_cdlhammer trader_cdlhangingman trader_cdlharami trader_cdlharamicross trader_cdlhighwave trader_cdlhikkake trader_cdlhikkakemod trader_cdlhomingpigeon trader_cdlidentical3crows trader_cdlinneck trader_cdlinvertedhammer trader_cdlkicking trader_cdlkickingbylength trader_cdlladderbottom trader_cdllongleggeddoji trader_cdllongline trader_cdlmarubozu trader_cdlmatchinglow trader_cdlmathold trader_cdlmorningdojistar trader_cdlmorningstar trader_cdlonneck trader_cdlpiercing trader_cdlrickshawman trader_cdlrisefall3methods trader_cdlseparatinglines trader_cdlshootingstar trader_cdlshortline trader_cdlspinningtop trader_cdlstalledpattern trader_cdlsticksandwich trader_cdltakuri trader_cdltasukigap trader_cdlthrusting trader_cdltristar trader_cdlunique3river trader_cdlupsidegap2crows trader_cdlxsidegap3methods trader_ceil trader_cmo trader_compatibility_default trader_compatibility_metastock trader_correl trader_cos trader_cosh trader_dema trader_div trader_dx trader_ema trader_err_alloc_err trader_err_bad_object trader_err_bad_param trader_err_func_not_found trader_err_group_not_found trader_err_input_not_all_initialize trader_err_internal_error trader_err_invalid_handle trader_err_invalid_list_type trader_err_invalid_param_function trader_err_invalid_param_holder trader_err_invalid_param_holder_type trader_err_lib_not_initialize trader_err_not_supported trader_err_out_of_range_end_index trader_err_out_of_range_start_index trader_err_output_not_all_initialize trader_err_success trader_err_unknown_error trader_errno trader_exp trader_floor trader_func_unst_adx trader_func_unst_adxr trader_func_unst_all trader_func_unst_atr trader_func_unst_cmo trader_func_unst_dx trader_func_unst_ema trader_func_unst_ht_dcperiod trader_func_unst_ht_dcphase trader_func_unst_ht_phasor trader_func_unst_ht_sine trader_func_unst_ht_trendline trader_func_unst_ht_trendmode trader_func_unst_kama trader_func_unst_mama trader_func_unst_mfi trader_func_unst_minus_di trader_func_unst_minus_dm trader_func_unst_natr trader_func_unst_none trader_func_unst_plus_di trader_func_unst_plus_dm trader_func_unst_rsi trader_func_unst_stochrsi trader_func_unst_t3 trader_get_compat trader_get_unstable_period trader_ht_dcperiod trader_ht_dcphase trader_ht_phasor trader_ht_sine trader_ht_trendline trader_ht_trendmode trader_kama trader_linearreg trader_linearreg_angle trader_linearreg_intercept trader_linearreg_slope trader_ln trader_log10 trader_ma trader_ma_type_dema trader_ma_type_ema trader_ma_type_kama trader_ma_type_mama trader_ma_type_sma trader_ma_type_t3 trader_ma_type_tema trader_ma_type_trima trader_ma_type_wma trader_macd trader_macdext trader_macdfix trader_mama trader_mavp trader_max trader_maxindex trader_medprice trader_mfi trader_midpoint trader_midprice trader_min trader_minindex trader_minmax trader_minmaxindex trader_minus_di trader_minus_dm trader_mom trader_mult trader_natr trader_obv trader_plus_di trader_plus_dm trader_ppo trader_real_max trader_real_min trader_roc trader_rocp trader_rocr trader_rocr100 trader_rsi trader_sar trader_sarext trader_set_compat trader_set_unstable_period trader_sin trader_sinh trader_sma trader_sqrt trader_stddev trader_stoch trader_stochf trader_stochrsi trader_sub trader_sum trader_t3 trader_tan trader_tanh trader_tema trader_trange trader_trima trader_trix trader_tsf trader_typprice trader_ultosc trader_var trader_wclprice trader_willr trader_wma trait trait_exists tran_commit_class_commit_instance tran_commit_class_uncommit_instance tran_rep_class_commit_instance tran_rep_class_rep_instance tran_rep_class_uncommit_instance tran_serializable transliterator_create transliterator_create_from_rules transliterator_create_inverse transliterator_get_error_code transliterator_get_error_message transliterator_list_ids transliterator_transliterate trap_brkpt trap_trace trigger_error trim true try typeapplication typeaudio typeimage typemessage typemodel typemultipart typeother typetext typevideo u_ambiguous_alias_warning u_bad_variable_definition u_brk_assign_error u_brk_error_limit u_brk_error_start u_brk_hex_digits_expected u_brk_init_error u_brk_internal_error u_brk_malformed_rule_tag u_brk_mismatched_paren u_brk_new_line_in_quoted_string u_brk_rule_empty_set u_brk_rule_syntax u_brk_semicolon_expected u_brk_unclosed_set u_brk_undefined_variable u_brk_unrecognized_option u_brk_variable_redfinition u_buffer_overflow_error u_ce_not_found_error u_collator_version_mismatch u_different_uca_version u_enum_out_of_sync_error u_error_limit u_error_warning_limit u_error_warning_start u_file_access_error u_fmt_parse_error_limit u_fmt_parse_error_start u_idna_ace_prefix_error u_idna_check_bidi_error u_idna_domain_name_too_long_error u_idna_error_limit u_idna_error_start u_idna_label_too_long_error u_idna_prohibited_error u_idna_std3_ascii_rules_error u_idna_unassigned_error u_idna_verification_error u_idna_zero_length_label_error u_illegal_argument_error u_illegal_char_found u_illegal_char_in_segment u_illegal_character u_illegal_escape_sequence u_illegal_pad_position u_index_outofbounds_error u_internal_program_error u_internal_transliterator_error u_invalid_char_found u_invalid_format_error u_invalid_function u_invalid_id u_invalid_property_pattern u_invalid_rbt_syntax u_invalid_state_error u_invalid_table_file u_invalid_table_format u_invariant_conversion_error u_malformed_exponential_pattern u_malformed_pragma u_malformed_rule u_malformed_set u_malformed_symbol_reference u_malformed_unicode_escape u_malformed_variable_definition u_malformed_variable_reference u_memory_allocation_error u_message_parse_error u_mismatched_segment_delimiters u_misplaced_anchor_start u_misplaced_compound_filter u_misplaced_cursor_offset u_misplaced_quantifier u_missing_operator u_missing_resource_error u_missing_segment_close u_multiple_ante_contexts u_multiple_compound_filters u_multiple_cursors u_multiple_decimal_separators u_multiple_decimal_seperators u_multiple_exponential_symbols u_multiple_pad_specifiers u_multiple_percent_symbols u_multiple_permill_symbols u_multiple_post_contexts u_no_space_available u_no_write_permission u_parse_error u_parse_error_limit u_parse_error_start u_pattern_syntax_error u_primary_too_long_error u_regex_bad_escape_sequence u_regex_bad_interval u_regex_error_limit u_regex_error_start u_regex_internal_error u_regex_invalid_back_ref u_regex_invalid_flag u_regex_invalid_state u_regex_look_behind_limit u_regex_max_lt_min u_regex_mismatched_paren u_regex_number_too_big u_regex_property_syntax u_regex_rule_syntax u_regex_set_contains_string u_regex_unimplemented u_resource_type_mismatch u_rule_mask_error u_safeclone_allocated_warning u_sort_key_too_short_warning u_standard_error_limit u_state_old_warning u_state_too_old_error u_string_not_terminated_warning u_stringprep_check_bidi_error u_stringprep_prohibited_error u_stringprep_unassigned_error u_too_many_aliases_error u_trailing_backslash u_truncated_char_found u_unclosed_segment u_undefined_segment_reference u_undefined_variable u_unexpected_token u_unmatched_braces u_unquoted_special u_unsupported_attribute u_unsupported_error u_unsupported_escape_sequence u_unsupported_property u_unterminated_quote u_useless_collator_error u_using_default_warning u_using_fallback_warning u_variable_range_exhausted u_variable_range_overlap u_zero_error uasort ucfirst ucwords udm_add_search_limit udm_alloc_agent udm_alloc_agent_array udm_api_version udm_cat_list udm_cat_path udm_check_charset udm_clear_search_limits udm_crc32 udm_errno udm_error udm_find udm_free_agent udm_free_ispell_data udm_free_res udm_get_doc_count udm_get_res_field udm_get_res_param udm_hash32 udm_load_ispell_data udm_set_agent_param uksort uloc_actual_locale uloc_valid_locale umask uniqid unixtojd unknown_type unlink unpack unregister_tick_function unserialize unset untaint upload_err_cant_write upload_err_extension upload_err_form_size upload_err_ini_size upload_err_no_file upload_err_no_tmp_dir upload_err_ok upload_err_partial urldecode urlencode use use_soap_error_handler user_error usleep usort utf8_decode utf8_encode var var_dump var_export varcmp_eq varcmp_gt varcmp_lt varcmp_null variant_abs variant_add variant_and variant_cast variant_cat variant_cmp variant_date_from_timestamp variant_date_to_timestamp variant_div variant_eqv variant_fix variant_get_type variant_idiv variant_imp variant_int variant_mod variant_mul variant_neg variant_not variant_or variant_pow variant_round variant_set variant_set_type variant_sub variant_xor version_compare vfprintf virtual void vpopmail_add_alias_domain vpopmail_add_alias_domain_ex vpopmail_add_domain vpopmail_add_domain_ex vpopmail_add_user vpopmail_alias_add vpopmail_alias_del vpopmail_alias_del_domain vpopmail_alias_get vpopmail_alias_get_all vpopmail_auth_user vpopmail_del_domain vpopmail_del_domain_ex vpopmail_del_user vpopmail_error vpopmail_passwd vpopmail_set_user_quota vprintf vsprintf vt_array vt_bool vt_bstr vt_byref vt_cy vt_date vt_decimal vt_dispatch vt_empty vt_error vt_i1 vt_i2 vt_i4 vt_int vt_null vt_r4 vt_r8 vt_ui1 vt_ui2 vt_ui4 vt_uint vt_unknown vt_variant wddx_add_vars wddx_deserialize wddx_packet_end wddx_packet_start wddx_serialize_value wddx_serialize_vars while win32_above_normal_priority_class win32_below_normal_priority_class win32_continue_service win32_create_service win32_delete_service win32_error_access_denied win32_error_circular_dependency win32_error_database_does_not_exist win32_error_dependent_services_running win32_error_duplicate_service_name win32_error_failed_service_controller_connect win32_error_insufficient_buffer win32_error_invalid_data win32_error_invalid_handle win32_error_invalid_level win32_error_invalid_name win32_error_invalid_parameter win32_error_invalid_service_account win32_error_invalid_service_control win32_error_path_not_found win32_error_service_already_running win32_error_service_cannot_accept_ctrl win32_error_service_database_locked win32_error_service_dependency_deleted win32_error_service_dependency_fail win32_error_service_disabled win32_error_service_does_not_exist win32_error_service_exists win32_error_service_logon_failed win32_error_service_marked_for_delete win32_error_service_no_thread win32_error_service_not_active win32_error_service_request_timeout win32_error_shutdown_in_progress win32_get_last_control_message win32_high_priority_class win32_idle_priority_class win32_no_error win32_normal_priority_class win32_pause_service win32_ps_list_procs win32_ps_stat_mem win32_ps_stat_proc win32_query_service_status win32_realtime_priority_class win32_service_accept_pause_continue win32_service_accept_preshutdown win32_service_accept_shutdown win32_service_accept_stop win32_service_auto_start win32_service_continue_pending win32_service_control_continue win32_service_control_interrogate win32_service_control_pause win32_service_control_preshutdown win32_service_control_shutdown win32_service_control_stop win32_service_demand_start win32_service_disabled win32_service_error_ignore win32_service_error_normal win32_service_interactive_process win32_service_pause_pending win32_service_paused win32_service_running win32_service_runs_in_system_process win32_service_start_pending win32_service_stop_pending win32_service_stopped win32_service_win32_own_process win32_service_win32_own_process_interactive win32_set_service_status win32_start_service win32_start_service_ctrl_dispatcher win32_stop_service wincache_fcache_fileinfo wincache_fcache_meminfo wincache_lock wincache_ocache_fileinfo wincache_ocache_meminfo wincache_refresh_if_changed wincache_rplist_fileinfo wincache_rplist_meminfo wincache_scache_info wincache_scache_meminfo wincache_ucache_add wincache_ucache_cas wincache_ucache_clear wincache_ucache_dec wincache_ucache_delete wincache_ucache_exists wincache_ucache_get wincache_ucache_inc wincache_ucache_info wincache_ucache_meminfo wincache_ucache_set wincache_unlock wnohang wordwrap wsdl_cache_both wsdl_cache_disk wsdl_cache_memory wsdl_cache_none wuntraced x509_purpose_any x509_purpose_crl_sign x509_purpose_ns_ssl_server x509_purpose_smime_encrypt x509_purpose_smime_sign x509_purpose_ssl_client x509_purpose_ssl_server xattr_create xattr_dontfollow xattr_get xattr_list xattr_remove xattr_replace xattr_root xattr_set xattr_supported xdiff_file_bdiff xdiff_file_bdiff_size xdiff_file_bpatch xdiff_file_diff xdiff_file_diff_binary xdiff_file_merge3 xdiff_file_patch xdiff_file_patch_binary xdiff_file_rabdiff xdiff_patch_normal xdiff_patch_reverse xdiff_string_bdiff xdiff_string_bdiff_size xdiff_string_bpatch xdiff_string_diff xdiff_string_diff_binary xdiff_string_merge3 xdiff_string_patch xdiff_string_patch_binary xdiff_string_rabdiff xhprof_disable xhprof_enable xhprof_sample_disable xhprof_sample_enable xml_attribute_cdata xml_attribute_decl_node xml_attribute_entity xml_attribute_enumeration xml_attribute_id xml_attribute_idref xml_attribute_idrefs xml_attribute_nmtoken xml_attribute_nmtokens xml_attribute_node xml_attribute_notation xml_cdata_section_node xml_comment_node xml_document_frag_node xml_document_node xml_document_type_node xml_dtd_node xml_element_decl_node xml_element_node xml_entity_decl_node xml_entity_node xml_entity_ref_node xml_error_async_entity xml_error_attribute_external_entity_ref xml_error_bad_char_ref xml_error_binary_entity_ref xml_error_duplicate_attribute xml_error_external_entity_handling xml_error_incorrect_encoding xml_error_invalid_token xml_error_junk_after_doc_element xml_error_misplaced_xml_pi xml_error_no_elements xml_error_no_memory xml_error_none xml_error_param_entity_ref xml_error_partial_char xml_error_recursive_entity_ref xml_error_string xml_error_syntax xml_error_tag_mismatch xml_error_unclosed_cdata_section xml_error_unclosed_token xml_error_undefined_entity xml_error_unknown_encoding xml_get_current_byte_index xml_get_current_column_number xml_get_current_line_number xml_get_error_code xml_html_document_node xml_local_namespace xml_namespace_decl_node xml_notation_node xml_option_case_folding xml_option_skip_tagstart xml_option_skip_white xml_option_target_encoding xml_parse xml_parse_into_struct xml_parser_create xml_parser_create_ns xml_parser_free xml_parser_get_option xml_parser_set_option xml_pi_node xml_sax_impl xml_set_character_data_handler xml_set_default_handler xml_set_element_handler xml_set_end_namespace_decl_handler xml_set_external_entity_ref_handler xml_set_notation_decl_handler xml_set_object xml_set_processing_instruction_handler xml_set_start_namespace_decl_handler xml_set_unparsed_entity_decl_handler xml_text_node xmlrpc_decode xmlrpc_decode_request xmlrpc_encode xmlrpc_encode_request xmlrpc_get_type xmlrpc_is_fault xmlrpc_parse_method_descriptions xmlrpc_server_add_introspection_data xmlrpc_server_call_method xmlrpc_server_create xmlrpc_server_destroy xmlrpc_server_register_introspection_callback xmlrpc_server_register_method xmlrpc_set_type xmlwriter_end_attribute xmlwriter_end_cdata xmlwriter_end_comment xmlwriter_end_document xmlwriter_end_dtd xmlwriter_end_dtd_attlist xmlwriter_end_dtd_element xmlwriter_end_dtd_entity xmlwriter_end_element xmlwriter_end_pi xmlwriter_flush xmlwriter_full_end_element xmlwriter_open_memory xmlwriter_open_uri xmlwriter_output_memory xmlwriter_set_indent xmlwriter_set_indent_string xmlwriter_start_attribute xmlwriter_start_attribute_ns xmlwriter_start_cdata xmlwriter_start_comment xmlwriter_start_document xmlwriter_start_dtd xmlwriter_start_dtd_attlist xmlwriter_start_dtd_element xmlwriter_start_dtd_entity xmlwriter_start_element xmlwriter_start_element_ns xmlwriter_start_pi xmlwriter_text xmlwriter_write_attribute xmlwriter_write_attribute_ns xmlwriter_write_cdata xmlwriter_write_comment xmlwriter_write_dtd xmlwriter_write_dtd_attlist xmlwriter_write_dtd_element xmlwriter_write_dtd_entity xmlwriter_write_element xmlwriter_write_element_ns xmlwriter_write_pi xmlwriter_write_raw xor xsd_1999_namespace xsd_1999_timeinstant xsd_anytype xsd_anyuri xsd_anyxml xsd_base64binary xsd_boolean xsd_byte xsd_date xsd_datetime xsd_decimal xsd_double xsd_duration xsd_entities xsd_entity xsd_float xsd_gday xsd_gmonth xsd_gmonthday xsd_gyear xsd_gyearmonth xsd_hexbinary xsd_id xsd_idref xsd_idrefs xsd_int xsd_integer xsd_language xsd_long xsd_name xsd_namespace xsd_ncname xsd_negativeinteger xsd_nmtoken xsd_nmtokens xsd_nonnegativeinteger xsd_nonpositiveinteger xsd_normalizedstring xsd_notation xsd_positiveinteger xsd_qname xsd_short xsd_string xsd_time xsd_token xsd_unsignedbyte xsd_unsignedint xsd_unsignedlong xsd_unsignedshort xsl_clone_always xsl_clone_auto xsl_clone_never xsl_secpref_create_directory xsl_secpref_default xsl_secpref_none xsl_secpref_read_file xsl_secpref_read_network xsl_secpref_write_file xsl_secpref_write_network yaml_any_break yaml_any_encoding yaml_any_scalar_style yaml_bool_tag yaml_cr_break yaml_crln_break yaml_double_quoted_scalar_style yaml_emit yaml_emit_file yaml_float_tag yaml_folded_scalar_style yaml_int_tag yaml_literal_scalar_style yaml_ln_break yaml_map_tag yaml_null_tag yaml_parse yaml_parse_file yaml_parse_url yaml_php_tag yaml_plain_scalar_style yaml_seq_tag yaml_single_quoted_scalar_style yaml_str_tag yaml_timestamp_tag yaml_utf16be_encoding yaml_utf16le_encoding yaml_utf8_encoding yesexpr yesstr yield zend_debug_build zend_logo_guid zend_multibyte zend_thread_id zend_thread_safe zend_version zip_close zip_entry_close zip_entry_compressedsize zip_entry_compressionmethod zip_entry_filesize zip_entry_name zip_entry_open zip_entry_read zip_open zip_read zlib_decode zlib_encode zlib_encoding_deflate zlib_encoding_gzip zlib_encoding_raw zlib_get_coding_type", +} + +L.styles = { + ["QUESTION MARK"] = { + id = 18, + fgColor = rgb(0xFF0000), + bgColor = rgb(0xFDF8E3), + }, + ["DEFAULT"] = { + id = 118, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFEFCF5), + }, + ["STRING"] = { + id = 119, + fgColor = rgb(0x808080), + bgColor = rgb(0xFEFCF5), + }, + ["COMPLEX VARIABLE"] = { + id = 104, + fgColor = rgb(0x808080), + bgColor = rgb(0xFEFCF5), + fontStyle = 1, + }, + ["STRING VARIABLE"] = { + id = 126, + fgColor = rgb(0x808080), + bgColor = rgb(0xFEFCF5), + fontStyle = 1, + }, + ["SIMPLESTRING"] = { + id = 120, + fgColor = rgb(0x808080), + bgColor = rgb(0xFEFCF5), + }, + ["WORD"] = { + id = 121, + fgColor = rgb(InstructionColor), + bgColor = rgb(0xFEFCF5), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 122, + fgColor = rgb(0xFF8000), + bgColor = rgb(0xFEFCF5), + }, + ["VARIABLE"] = { + id = 123, + fgColor = rgb(OperatorColor), + bgColor = rgb(0xFEFCF5), + }, + ["COMMENT"] = { + id = 124, + fgColor = rgb(0x008000), + bgColor = rgb(0xFEFCF5), + }, + ["COMMENTLINE"] = { + id = 125, + fgColor = rgb(0x008000), + bgColor = rgb(0xFEFCF5), + }, + ["OPERATOR"] = { + id = 127, + fgColor = rgb(TypeColor), + bgColor = rgb(0xFEFCF5), + }, +} +return L diff --git a/src/NotepadNext/languages/postscript.lua b/src/NotepadNext/languages/postscript.lua new file mode 100644 index 000000000..4933636e9 --- /dev/null +++ b/src/NotepadNext/languages/postscript.lua @@ -0,0 +1,107 @@ +local L = {} + +L.lexer = "postscript" + +L.singleLineComment = "% " + +L.extensions = { + "ps", +} + +L.keywords = { + [0] = "$error = == FontDirectory StandardEncoding UserObjects abs add aload anchorsearch and arc arcn arcto array ashow astore atan awidthshow begin bind bitshift bytesavailable cachestatus ceiling charpath clear cleardictstack cleartomark clip clippath closefile closepath concat concatmatrix copy copypage cos count countdictstack countexecstack counttomark currentcmykcolor currentcolorspace currentdash currentdict currentfile currentflat currentfont currentgray currenthsbcolor currentlinecap currentlinejoin currentlinewidth currentmatrix currentmiterlimit currentpagedevice currentpoint currentrgbcolor currentscreen currenttransfer cvi cvlit cvn cvr cvrs cvs cvx def defaultmatrix definefont dict dictstack div dtransform dup echo end eoclip eofill eq erasepage errordict exch exec execstack executeonly executive exit exp false file fill findfont flattenpath floor flush flushfile for forall ge get getinterval grestore grestoreall gsave gt idetmatrix idiv idtransform if ifelse image imagemask index initclip initgraphics initmatrix inustroke invertmatrix itransform known kshow le length lineto ln load log loop lt makefont mark matrix maxlength mod moveto mul ne neg newpath noaccess nor not null nulldevice or pathbbox pathforall pop print prompt pstack put putinterval quit rand rcheck rcurveto read readhexstring readline readonly readstring rectstroke repeat resetfile restore reversepath rlineto rmoveto roll rotate round rrand run save scale scalefont search setblackgeneration setcachedevice setcachelimit setcharwidth setcolorscreen setcolortransfer setdash setflat setfont setgray sethsbcolor setlinecap setlinejoin setlinewidth setmatrix setmiterlimit setpagedevice setrgbcolor setscreen settransfer setvmthreshold show showpage sin sqrt srand stack start status statusdict stop stopped store string stringwidth stroke strokepath sub systemdict token transform translate true truncate type ueofill undefineresource userdict usertime version vmstatus wcheck where widthshow write writehexstring writestring xcheck xor", + [1] = "GlobalFontDirectory ISOLatin1Encoding SharedFontDirectory UserObject arct colorimage cshow currentblackgeneration currentcacheparams currentcmykcolor currentcolor currentcolorrendering currentcolorscreen currentcolorspace currentcolortransfer currentdevparams currentglobal currentgstate currenthalftone currentobjectformat currentoverprint currentpacking currentpagedevice currentshared currentstrokeadjust currentsystemparams currentundercolorremoval currentuserparams defineresource defineuserobject deletefile execform execuserobject filenameforall fileposition filter findencoding findresource gcheck globaldict glyphshow gstate ineofill infill instroke inueofill inufill inustroke languagelevel makepattern packedarray printobject product realtime rectclip rectfill rectstroke renamefile resourceforall resourcestatus revision rootfont scheck selectfont serialnumber setbbox setblackgeneration setcachedevice2 setcacheparams setcmykcolor setcolor setcolorrendering setcolorscreen setcolorspace setcolortranfer setdevparams setfileposition setglobal setgstate sethalftone setobjectformat setoverprint setpacking setpagedevice setpattern setshared setstrokeadjust setsystemparams setucacheparams setundercolorremoval setuserparams setvmthreshold shareddict startjob uappend ucache ucachestatus ueofill ufill undef undefinefont undefineresource undefineuserobject upath ustroke ustrokepath vmreclaim writeobject xshow xyshow yshow", + [2] = "cliprestore clipsave composefont currentsmoothness findcolorrendering setsmoothness shfill", + [3] = ".begintransparencygroup .begintransparencymask .bytestring .charboxpath .currentaccuratecurves .currentblendmode .currentcurvejoin .currentdashadapt .currentdotlength .currentfilladjust2 .currentlimitclamp .currentopacityalpha .currentoverprintmode .currentrasterop .currentshapealpha .currentsourcetransparent .currenttextknockout .currenttexturetransparent .dashpath .dicttomark .discardtransparencygroup .discardtransparencymask .endtransparencygroup .endtransparencymask .execn .filename .fileposition .forceput .forceundef .forgetsave .getbitsrect .getdevice .inittransparencymask .knownget .locksafe .makeoperator .namestring .oserrno .oserrorstring .peekstring .rectappend .runandhide .setaccuratecurves .setblendmode .setcurvejoin .setdashadapt .setdebug .setdefaultmatrix .setdotlength .setfilladjust2 .setlimitclamp .setmaxlength .setopacityalpha .setoverprintmode .setrasterop .setsafe .setshapealpha .setsourcetransparent .settextknockout .settexturetransparent .stringbreak .stringmatch .tempfile .type1decrypt .type1encrypt .type1execchar .unread arccos arcsin copydevice copyscanlines currentdevice finddevice findlibfile findprotodevice flushpage getdeviceprops getenv makeimagedevice makewordimagedevice max min putdeviceprops setdevice", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["DSC COMMENT"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["DSC VALUE"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["Name"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION"] = { + id = 6, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["LITERAL"] = { + id = 7, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IMMEVAL"] = { + id = 8, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PAREN ARRAY"] = { + id = 9, + fgColor = rgb(0xFF00FF), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PAREN DICT"] = { + id = 10, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PAREN PROC"] = { + id = 11, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TEXT"] = { + id = 12, + fgColor = rgb(0x808000), + bgColor = rgb(defaultBg), + }, + ["HEX STRING"] = { + id = 13, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["BASE85 STRING"] = { + id = 14, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["BAD STRING CHAR"] = { + id = 15, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/powershell.lua b/src/NotepadNext/languages/powershell.lua new file mode 100644 index 000000000..c7906b331 --- /dev/null +++ b/src/NotepadNext/languages/powershell.lua @@ -0,0 +1,95 @@ +local L = {} + +L.lexer = "powershell" + +L.singleLineComment = "# " + +L.extensions = { + "ps1", + "psm1", +} + +L.keywords = { + [0] = "break continue do else elseif filter for foreach function if in return switch until where while", + [1] = "add-content add-history add-member add-pssnapin clear-content clear-item clear-itemproperty clear-variable compare-object convertfrom-securestring convert-path convertto-html convertto-securestring copy-item copy-itemproperty export-alias export-clixml export-console export-csv foreach-object format-custom format-list format-table format-wide get-acl get-alias get-authenticodesignature get-childitem get-command get-content get-credential get-culture get-date get-eventlog get-executionpolicy get-help get-history get-host get-item get-itemproperty get-location get-member get-pfxcertificate get-process get-psdrive get-psprovider get-pssnapin get-service get-tracesource get-uiculture get-unique get-variable get-wmiobject group-object import-alias import-clixml import-csv invoke-expression invoke-history invoke-item join-path measure-command measure-object move-item move-itemproperty new-alias new-item new-itemproperty new-object new-psdrive new-service new-timespan new-variable out-default out-file out-host out-null out-printer out-string pop-location push-location read-host remove-item remove-itemproperty remove-psdrive remove-pssnapin remove-variable rename-item rename-itemproperty resolve-path restart-service resume-service select-object select-string set-acl set-alias set-authenticodesignature set-content set-date set-executionpolicy set-item set-itemproperty set-location set-psdebug set-service set-tracesource set-variable sort-object split-path start-service start-sleep start-transcript stop-process stop-service stop-transcript suspend-service tee-object test-path trace-command update-formatdata update-typedata where-object write-debug write-error write-host write-output write-progress write-verbose write-warning", + [2] = "ac asnp clc cli clp clv cpi cpp cvpa diff epal epcsv fc fl foreach ft fw gal gc gci gcm gdr ghy gi gl gm gp gps group gsv gsnp gu gv gwmi iex ihy ii ipal ipcsv mi mp nal ndr ni nv oh rdr ri rni rnp rp rsnp rv rvpa sal sasv sc select si sl sleep sort sp spps spsv sv tee where write cat cd clear cp h history kill lp ls mount mv popd ps pushd pwd r rm rmdir echo cls chdir copy del dir erase move rd ren set type", + [5] = "component description example externalhelp forwardhelpcategory forwardhelptargetname functionality inputs link notes outputs parameter remotehelprunspace role synopsis", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 2, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["VARIABLE"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["INSTRUCTION WORD"] = { + id = 8, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["CMDLET"] = { + id = 9, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["ALIAS"] = { + id = 10, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["COMMENT STREAM"] = { + id = 13, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["HERE STRING"] = { + id = 14, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["HERE CHARACTER"] = { + id = 15, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 16, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/props.lua b/src/NotepadNext/languages/props.lua new file mode 100644 index 000000000..4cb72a980 --- /dev/null +++ b/src/NotepadNext/languages/props.lua @@ -0,0 +1,49 @@ +local L = {} + +L.lexer = "props" + +L.singleLineComment = "# " + +L.extensions = { + "properties", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["SECTION"] = { + id = 2, + fgColor = rgb(TypeColor), + bgColor = rgb(0xF2F4FF), + fontStyle = 1, + }, + ["ASSIGNMENT"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DEFVAL"] = { + id = 4, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["KEY"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, +} +return L diff --git a/src/NotepadNext/languages/purebasic.lua b/src/NotepadNext/languages/purebasic.lua new file mode 100644 index 000000000..62d9118a3 --- /dev/null +++ b/src/NotepadNext/languages/purebasic.lua @@ -0,0 +1,95 @@ +local L = {} + +L.lexer = "purebasic" + +L.singleLineComment = "; " + +L.extensions = { + "pb", +} + +L.keywords = { + [0] = "and break case continue data datasection declare declarecdll declaredll default deftype dim else elseif end enddatasection endenumeration endif endinterface endprocedure endselect endstructure endstructureunion enumeration extends fakereturn for foreach forever global gosub goto if includebinary includefile includepath interface newlist next or procedure procedurecdll proceduredll procedurereturn protected read repeat restore return select shared static step structure structureunion to until wend while xincludefile", + [1] = "compilercase compilerdefault compilerelse compilerendif compilerendselect compilerif compilerselect", + [2] = "None", + [3] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD1"] = { + id = 3, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 4, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEYWORD2"] = { + id = 10, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["KEYWORD3"] = { + id = 11, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD4"] = { + id = 12, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["CONSTANT"] = { + id = 13, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["LABEL"] = { + id = 15, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["ERROR"] = { + id = 16, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["HEXNUMBER"] = { + id = 17, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["BINNUMBER"] = { + id = 18, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/python.lua b/src/NotepadNext/languages/python.lua new file mode 100644 index 000000000..c13a9a600 --- /dev/null +++ b/src/NotepadNext/languages/python.lua @@ -0,0 +1,132 @@ +local L = {} + +L.lexer = "python" + +L.singleLineComment = "# " + +L.tabSize = 4 + +L.tabSettings = "spaces" + +L.first_line = { + "^#!.*python" +} + +L.extensions = { + "py", + "pyw", +} + +L.properties = { + ["lexer.python.keywords2.no.sub.identifiers"] = "1", + ["lexer.python.decorator.attributes"] = "1" +} + +L.keywords = { + [0] = "and as assert async await break case class continue def del elif else except finally for from global if import in is lambda match nonlocal not or pass raise return try while with yield self", + [1] = "ArithmeticError AssertionError AttributeError BaseException BlockingIOError BrokenPipeError BufferError BytesWarning ChildProcessError ConnectionAbortedError ConnectionError ConnectionRefusedError ConnectionResetError DeprecationWarning EOFError Ellipsis EnvironmentError Exception False FileExistsError FileNotFoundError FloatingPointError FutureWarning GeneratorExit IOError ImportError ImportWarning IndentationError IndexError InterruptedError IsADirectoryError KeyError KeyboardInterrupt LookupError MemoryError ModuleNotFoundError NameError None NotADirectoryError NotImplemented NotImplementedError OSError OverflowError PendingDeprecationWarning PermissionError ProcessLookupError RecursionError ReferenceError ResourceWarning RuntimeError RuntimeWarning StopAsyncIteration StopIteration SyntaxError SyntaxWarning SystemError SystemExit TabError TimeoutError True TypeError UnboundLocalError UnicodeDecodeError UnicodeEncodeError UnicodeError UnicodeTranslateError UnicodeWarning UserWarning ValueError Warning WindowsError ZeroDivisionError abs all any ascii bin bool breakpoint bytearray bytes callable chr classmethod compile complex copyright credits delattr dict dir divmod enumerate eval exec exit filter float format frozenset getattr globals hasattr hash help hex id input int isinstance issubclass iter len license list locals map max memoryview min next object oct open ord pow print property quit range repr reversed round set setattr slice sorted staticmethod str sum super tuple type vars zip", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENTLINE"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 3, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 4, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["KEYWORDS"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["BUILTINS"] = { + id = 14, + fgColor = rgb(0x880088), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TRIPLE"] = { + id = 6, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["TRIPLEDOUBLE"] = { + id = 7, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["CLASSNAME"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DEFNAME"] = { + id = 9, + fgColor = rgb(0xFF00FF), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENTBLOCK"] = { + id = 12, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["DECORATOR"] = { + id = 15, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["F STRING"] = { + id = 16, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["F CHARACTER"] = { + id = 17, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["F TRIPLE"] = { + id = 18, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["F TRIPLEDOUBLE"] = { + id = 19, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/r.lua b/src/NotepadNext/languages/r.lua new file mode 100644 index 000000000..b7595e1fd --- /dev/null +++ b/src/NotepadNext/languages/r.lua @@ -0,0 +1,78 @@ +local L = {} + +L.lexer = "r" + +L.singleLineComment = "# " + +L.extensions = { + "r", + "s", + "splus", +} + +L.keywords = { + [0] = "if else repeat while function for in next break TRUE FALSE NULL NA Inf NaN", + [1] = "abbreviate abline abs acf acos acosh addmargins aggregate agrep alarm alias alist all anova any aov aperm append apply approx approxfun apropos ar args arima array arrows asin asinh assign assocplot atan atanh attach attr attributes autoload autoloader ave axis backsolve barplot basename beta bindtextdomain binomial biplot bitmap bmp body box boxplot bquote break browser builtins bxp by bzfile c call cancor capabilities casefold cat category cbind ccf ceiling character charmatch chartr chol choose chull citation class close cm cmdscale codes coef coefficients col colnames colors colorspaces colours comment complex confint conflicts contour contrasts contributors convolve cophenetic coplot cor cos cosh cov covratio cpgram crossprod cummax cummin cumprod cumsum curve cut cutree cycle data dataentry date dbeta dbinom dcauchy dchisq de debug debugger decompose delay deltat demo dendrapply density deparse deriv det detach determinant deviance dexp df dfbeta dfbetas dffits dgamma dgeom dget dhyper diag diff diffinv difftime digamma dim dimnames dir dirname dist dlnorm dlogis dmultinom dnbinom dnorm dotchart double dpois dput drop dsignrank dt dump dunif duplicated dweibull dwilcox eapply ecdf edit effects eigen emacs embed end environment eval evalq example exists exp expression factanal factor factorial family fft fifo file filter find fitted fivenum fix floor flush for force formals format formula forwardsolve fourfoldplot frame frequency ftable function gamma gaussian gc gcinfo gctorture get getenv geterrmessage gettext gettextf getwd gl glm globalenv gray grep grey grid gsub gzcon gzfile hat hatvalues hcl hclust head heatmap help hist history hsv httpclient iconv iconvlist identical identify if ifelse image influence inherits integer integrate interaction interactive intersect invisible isoreg jitter jpeg julian kappa kernapply kernel kmeans knots kronecker ksmooth labels lag lapply layout lbeta lchoose lcm legend length letters levels lfactorial lgamma library licence license line lines list lm load loadhistory loadings local locator loess log logb logical loglin lowess ls lsfit machine mad mahalanobis makepredictcall manova mapply match matlines matplot matpoints matrix max mean median medpolish menu merge message methods mget min missing mode monthplot months mosaicplot mtext mvfft names napredict naprint naresid nargs nchar ncol next nextn ngettext nlevels nlm nls noquote nrow numeric objects offset open optim optimise optimize options order ordered outer pacf page pairlist pairs palette par parse paste pbeta pbinom pbirthday pcauchy pchisq pdf pentagamma person persp pexp pf pgamma pgeom phyper pi pico pictex pie piechart pipe plclust plnorm plogis plot pmatch pmax pmin pnbinom png pnorm points poisson poly polygon polym polyroot postscript power ppoints ppois ppr prcomp predict preplot pretty princomp print prmatrix prod profile profiler proj promax prompt provide psigamma psignrank pt ptukey punif pweibull pwilcox q qbeta qbinom qbirthday qcauchy qchisq qexp qf qgamma qgeom qhyper qlnorm qlogis qnbinom qnorm qpois qqline qqnorm qqplot qr qsignrank qt qtukey quantile quarters quasi quasibinomial quasipoisson quit qunif quote qweibull qwilcox rainbow range rank raw rbeta rbind rbinom rcauchy rchisq readline real recover rect reformulate regexpr relevel remove reorder rep repeat replace replicate replications require reshape resid residuals restart return rev rexp rf rgamma rgb rgeom rhyper rle rlnorm rlogis rm rmultinom rnbinom rnorm round row rownames rowsum rpois rsignrank rstandard rstudent rt rug runif runmed rweibull rwilcox sample sapply save savehistory scale scan screen screeplot sd search searchpaths seek segments seq sequence serialize setdiff setequal setwd shell sign signif sin single sinh sink smooth solve sort source spectrum spline splinefun split sprintf sqrt stack stars start stderr stdin stdout stem step stepfun stl stop stopifnot str strftime strheight stripchart strptime strsplit strtrim structure strwidth strwrap sub subset substitute substr substring sum summary sunflowerplot supsmu svd sweep switch symbols symnum system t table tabulate tail tan tanh tapply tempdir tempfile termplot terms tetragamma text time title toeplitz tolower topenv toupper trace traceback transform trigamma trunc truncate try ts tsdiag tsp typeof unclass undebug union unique uniroot unix unlink unlist unname unserialize unsplit unstack untrace unz update upgrade url var varimax vcov vector version vi vignette warning warnings weekdays weights which while window windows with write wsbrowser xedit xemacs xfig xinch xor xtabs xyinch yinch zapsmall", + [2] = "acme aids aircondit amis aml banking barchart barley beaver bigcity boot brambles breslow bs bwplot calcium cane capability cav censboot channing city claridge cloth cloud coal condense contourplot control corr darwin densityplot dogs dotplot ducks empinf envelope environmental ethanol fir frets gpar grav gravity grob hirose histogram islay knn larrows levelplot llines logit lpoints lsegments lset ltext lvqinit lvqtest manaus melanoma motor multiedit neuro nitrofen nodal ns nuclear oneway parallel paulsen poisons polar qq qqmath remission rfs saddle salinity shingle simplex singer somgrid splom stripplot survival tau tmd tsboot tuna unit urine viewport wireframe wool xyplot", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 2, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["BASE WORD"] = { + id = 3, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["KEYWORD"] = { + id = 4, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 5, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING2"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 8, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["INFIX"] = { + id = 10, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/rc.lua b/src/NotepadNext/languages/rc.lua new file mode 100644 index 000000000..e8abe3e9d --- /dev/null +++ b/src/NotepadNext/languages/rc.lua @@ -0,0 +1,111 @@ +local L = {} + +L.lexer = "rc" + +L.singleLineComment = "// " + +L.extensions = { + "rc", +} + +L.keywords = { + [0] = "ACCELERATORS ALT AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON BEGIN BITMAP BLOCK BUTTON CAPTION CHARACTERISTICS CHECKBOX CLASS COMBOBOX CONTROL CTEXT CURSOR DEFPUSHBUTTON DIALOG DIALOGEX DISCARDABLE EDITTEXT END EXSTYLE FONT GROUPBOX ICON LANGUAGE LISTBOX LTEXT MENU MENUEX MENUITEM MESSAGETABLE POPUP PUSHBUTTON RADIOBUTTON RCDATA RTEXT SCROLLBAR SEPARATOR SHIFT STATE3 STRINGTABLE STYLE TEXTINCLUDE VALUE VERSION VERSIONINFO VIRTKEY", +} + +L.styles = { + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT"] = { + id = 23, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT DOC"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/rebol.lua b/src/NotepadNext/languages/rebol.lua new file mode 100644 index 000000000..fc455262a --- /dev/null +++ b/src/NotepadNext/languages/rebol.lua @@ -0,0 +1,176 @@ +local L = {} + +L.lexer = "rebol" + +L.singleLineComment = "; " + +L.extensions = { + "r2", + "r3", + "reb", +} + +L.keywords = { + [0] = "about abs absolute add alert alias all alter and any any-block? any-function? any-string? any-type? any-word? append arccosine arcsine arctangent array as-pair ask at attempt back binary? bind bitset? block? break brightness? browse build-tag caret-to-offset catch center-face change change-dir char? charset checksum choose clean-path clear clear-fields close comment complement component? compose compress confirm connected? construct context copy cosine datatype? date? debase decimal? decode-cgi decompress dehex delete detab difference dir? dirize disarm dispatch divide do do-events does dump-face dump-obj echo either else email? empty? enbase entab equal? error? even? event? exclude exists? exit exp extract fifth file? find first flash focus for forall foreach forever form forskip found? fourth free func function function? get get-modes get-word? greater-or-equal? greater? halt has hash? head head? help hide hide-popup if image? import-email in in-window? index? info? inform input input? insert integer? intersect issue? join last launch layout length? lesser-or-equal? lesser? library? license link? list-dir list? lit-path? lit-word? load load-image log-10 log-2 log-e logic? loop lowercase make make-dir make-face max maximum maximum-of min minimum minimum-of modified? mold money? multiply native? negate negative? next none? not not-equal? now number? object? odd? offset-to-caret offset? op? open or pair? paren? parse parse-xml path? pick poke port? positive? power prin print probe protect protect-system query quit random read read-io recycle reduce refinement? reform rejoin remainder remold remove remove-each rename repeat repend replace request request-color request-date request-download request-file request-list request-pass request-text resend return reverse routine? same? save script? second secure select send series? set set-modes set-net set-path? set-word? show show-popup sign? sine size-text size? skip sort source span? split-path square-root strict-equal? strict-not-equal? string? struct? stylize subtract suffix? switch tag? tail tail? tangent third throw time? to to-binary to-bitset to-block to-char to-date to-decimal to-email to-file to-get-word to-hash to-hex to-idate to-image to-integer to-issue to-list to-lit-path to-lit-word to-local-file to-logic to-money to-pair to-paren to-path to-rebol-file to-refinement to-set-path to-set-word to-string to-tag to-time to-tuple to-url to-word trace trim try tuple? type? unfocus union unique unprotect unset unset? until unview update upgrade uppercase url? usage use value? view viewed? wait what what-dir while within? word? write write-io xor zero?", + [1] = "action? any-block? any-function? any-string? any-type? any-word? binary? bitset? block? char? component? connected? datatype? date? decimal? dir? email? empty? equal? error? even? event? exists? file? found? function? get-word? greater-or-equal greater? hash? head? image? index? info? input? integer? issue? length? lesser-or-equal? lesser? library? link-app? link? list? lit-path? lit-word? logic? modified? money? native? negative? none? not-equal? number? object? odd? offset? op? pair? paren? path? port? positive? rebol-command? rebol-encap? rebol-link? rebol-pro? rebol-view? refinement? routine? same? script? series? set-path? set-word? sign? size? strict-equal? strict-not-equal string? struct? suffix? tag? tail? time? tuple? type? unset? url? value? view? word? zero?", + [2] = "action! any-block! any-function! any-string! any-type! any-word! binary! bitset! block! char! datatype! date! decimal! email! error! event! file! function! get-word! hash! image! integer! issue! library! list! lit-path! lit-word! logic! money! native! none! number! object! op! pair! paren! path! port! refinement! routine! series! set-path! set-word! string! struct! symbol! tag! time! tuple! unset! url! word!", + [3] = "None", + [4] = "None", + [5] = "None", + [6] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 32, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["ANY OTHER TEXT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["LINE COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["BLOCK COMMENT"] = { + id = 2, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["PREFACE"] = { + id = 3, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["OPERATORS"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["CHARACTERS"] = { + id = 5, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["STRING WITH QUOTES"] = { + id = 6, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["STRING WITH BRACES"] = { + id = 7, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 8, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["PAIR ( 800X600 )"] = { + id = 9, + fgColor = rgb(0x005090), + bgColor = rgb(defaultBg), + }, + ["TUPLE ( 127.0.0.1 )"] = { + id = 10, + fgColor = rgb(0x005090), + bgColor = rgb(defaultBg), + }, + ["BINARY ( 16#{1A803F59} )"] = { + id = 11, + fgColor = rgb(0xC000C0), + bgColor = rgb(defaultBg), + }, + ["MONEY"] = { + id = 12, + fgColor = rgb(0x003070), + bgColor = rgb(defaultBg), + }, + ["ISSUE { #123-CD-456 }"] = { + id = 13, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["TAG { }"] = { + id = 14, + fgColor = rgb(0xC00000), + bgColor = rgb(defaultBg), + }, + ["FILE { %/C/WINNT/SOME.DLL }"] = { + id = 15, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["EMAIL { JOE@MAIL.DOM }"] = { + id = 16, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["URL { FTP://THERE.DOM }"] = { + id = 17, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["DATE { 17-FEB-2004 1/3/99 }"] = { + id = 18, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["TIME { 12:30 11:22:59 01:59:59.123 }"] = { + id = 19, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIERS"] = { + id = 20, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEYWORD (ALL)"] = { + id = 21, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD (TEST FUNCTIONS)"] = { + id = 22, + fgColor = rgb(0x8000C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD (DATATYPES)"] = { + id = 23, + fgColor = rgb(0x800060), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD 4"] = { + id = 24, + fgColor = rgb(0xDD9900), + bgColor = rgb(defaultBg), + }, + ["KEYWORD 5"] = { + id = 25, + fgColor = rgb(0xDD9900), + bgColor = rgb(defaultBg), + }, + ["KEYWORD 6"] = { + id = 26, + fgColor = rgb(0xDD9900), + bgColor = rgb(defaultBg), + }, + ["KEYWORD 7"] = { + id = 27, + fgColor = rgb(0xDD9900), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/registry.lua b/src/NotepadNext/languages/registry.lua new file mode 100644 index 000000000..8e0297580 --- /dev/null +++ b/src/NotepadNext/languages/registry.lua @@ -0,0 +1,89 @@ +local L = {} + +L.lexer = "registry" + +L.singleLineComment = "; " + +L.extensions = { + "reg", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT STYLE"] = { + id = 32, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["VALUE NAME"] = { + id = 2, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 3, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["HEX DIGIT"] = { + id = 4, + fgColor = rgb(0x7F0B0C), + bgColor = rgb(defaultBg), + }, + ["VALUE TYPE"] = { + id = 5, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["ADDED KEY"] = { + id = 6, + fgColor = rgb(0x530155), + bgColor = rgb(defaultBg), + }, + ["REMOVED KEY"] = { + id = 7, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["ESCAPED CHARACTERS IN STRINGS"] = { + id = 8, + fgColor = rgb(0x7D8187), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["GUID IN KEY PATH"] = { + id = 9, + fgColor = rgb(0x7B5F15), + bgColor = rgb(defaultBg), + }, + ["GUID IN STRING"] = { + id = 10, + fgColor = rgb(0x7B5F15), + bgColor = rgb(defaultBg), + }, + ["PARAMETER"] = { + id = 11, + fgColor = rgb(0x0B6561), + bgColor = rgb(defaultBg), + }, + ["OPERATORS"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, +} +return L diff --git a/src/NotepadNext/languages/ruby.lua b/src/NotepadNext/languages/ruby.lua new file mode 100644 index 000000000..0b1641cea --- /dev/null +++ b/src/NotepadNext/languages/ruby.lua @@ -0,0 +1,129 @@ +local L = {} + +L.lexer = "ruby" + +L.singleLineComment = "# " + +L.extensions = { + "rb", + "rbw", +} + +L.keywords = { + [0] = "ARGF ARGV BEGIN END ENV FALSE DATA NIL RUBY_PATCHLEVEL RUBY_PLATFORM RUBY_RELEASE_DATE RUBY_VERSION PLATFORM RELEASE_DATE STDERR STDIN STDOUT TOPLEVEL_BINDING TRUE __ENCODING__ __END__ __FILE__ __LINE__ alias and begin break case class def defined? do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["ERROR"] = { + id = 1, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENTLINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["POD"] = { + id = 3, + fgColor = rgb(0x004000), + bgColor = rgb(0xC0FFC0), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808000), + bgColor = rgb(defaultBg), + }, + ["CLASS NAME"] = { + id = 8, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DEF NAME"] = { + id = 9, + fgColor = rgb(0x8080FF), + bgColor = rgb(0xFFFFCC), + fontStyle = 1, + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 12, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["GLOBAL"] = { + id = 13, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SYMBOL"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["MODULE NAME"] = { + id = 15, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["INSTANCE VAR"] = { + id = 16, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CLASS VAR"] = { + id = 17, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["BACKTICKS"] = { + id = 18, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xA08080), + }, + ["DATA SECTION"] = { + id = 19, + fgColor = rgb(0x600000), + bgColor = rgb(0xFFF0D8), + }, + ["STRING Q"] = { + id = 24, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/rust.lua b/src/NotepadNext/languages/rust.lua new file mode 100644 index 000000000..1b0728631 --- /dev/null +++ b/src/NotepadNext/languages/rust.lua @@ -0,0 +1,155 @@ +local L = {} + +L.lexer = "rust" + +L.singleLineComment = "// " + +L.extensions = { + "rs", +} + +L.keywords = { + [0] = "abstract as async become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self static struct super trait true try type typeof unsafe unsized use virtual where while yield", + [1] = "bool char f32 f64 i128 i16 i32 i64 i8 isize str u128 u16 u32 u64 u8 usize", + [2] = "Self", + [3] = "None", + [4] = "None", + [5] = "None", + [6] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 32, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["WHITESPACE"] = { + id = 0, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["BLOCK COMMENT"] = { + id = 1, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["LINE COMMENT"] = { + id = 2, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, + ["BLOCK DOC COMMENT"] = { + id = 3, + fgColor = rgb(0x3F703F), + bgColor = rgb(defaultBg), + }, + ["LINE DOC COMMENT"] = { + id = 4, + fgColor = rgb(0x3F703F), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 5, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["KEYWORDS 1"] = { + id = 6, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS 2"] = { + id = 7, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS 3"] = { + id = 8, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORDS 4"] = { + id = 9, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS 5"] = { + id = 10, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS 6"] = { + id = 11, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORDS 7"] = { + id = 12, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["REGULAR STRING"] = { + id = 13, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["RAW STRING"] = { + id = 14, + fgColor = rgb(0xB090B0), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 15, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 16, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 17, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["LIFETIME"] = { + id = 18, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["MACRO"] = { + id = 19, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["LEXICAL ERROR"] = { + id = 20, + fgColor = rgb(defaultFg), + bgColor = rgb(0xE0C0E0), + }, + ["BYTE STRING"] = { + id = 21, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["RAW BYTE STRING"] = { + id = 22, + fgColor = rgb(0xB090B0), + bgColor = rgb(defaultBg), + }, + ["BYTE CHARACTER"] = { + id = 23, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/scheme.lua b/src/NotepadNext/languages/scheme.lua new file mode 100644 index 000000000..d1754612d --- /dev/null +++ b/src/NotepadNext/languages/scheme.lua @@ -0,0 +1,79 @@ +local L = {} + +L.lexer = "scheme" + +L.singleLineComment = "; " + +L.extensions = { + "scm", + "smd", + "ss", +} + +L.keywords = { + [0] = "+ - * / = < > <= >= => abs acos and angle append apply asin assoc assq assv atan begin boolean? caar cadr call-with-current-continuation call/cc call-with-input-file call-with-output-file call-with-values car cdr cdar cddr caaar caadr cadar caddr cdaar cdadr cddar cdddr caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr case ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cond cons cos current-input-port current-output-port define define-syntax delay denominator display do dynamic-wind else eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt floor for-each force gcd if imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lambda lcm length let let* let-syntax letrec letrec-syntax list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector map max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file or output-port? pair? peek-char positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? syntax-rules transcript-off transcript-on truncate unquote unquote-splicing values vector vector->list vector-fill! vector-length vector-ref vector-set! vector? with-input-from-file with-output-to-file write write-char zero?", + [1] = "None", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENTLINE"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["FUNCTION WORD"] = { + id = 3, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["FUNCTION WORD2"] = { + id = 4, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SYMBOL"] = { + id = 5, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 9, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SPECIAL"] = { + id = 11, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 12, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/scss.lua b/src/NotepadNext/languages/scss.lua new file mode 100644 index 000000000..e19de3cd0 --- /dev/null +++ b/src/NotepadNext/languages/scss.lua @@ -0,0 +1,93 @@ +local L = {} + +L.lexer = "css" + +L.singleLineComment = "// " + +L.extensions = { + "scss", +} + +L.properties = { + ["lexer.css.scss.language"] = "1", +} + +L.keywords = { + [0] = "-khtml-background-clip -khtml-background-origin -khtml-background-size -khtml-border-bottom-left-radius -khtml-border-bottom-right-radius -khtml-border-radius -khtml-border-top-left-radius -khtml-border-top-right-radius -khtml-opacity -moz-animation -moz-animation-delay -moz-animation-direction -moz-animation-duration -moz-animation-fill-mode -moz-animation-iteration-count -moz-animation-name -moz-animation-play-state -moz-animation-timing-function -moz-appearance -moz-background-clip -moz-background-inline-policy -moz-background-origin -moz-background-size -moz-binding -moz-border-bottom-colors -moz-border-end -moz-border-end-color -moz-border-end-style -moz-border-end-width -moz-border-image -moz-border-left-colors -moz-border-radius -moz-border-radius-bottomleft -moz-border-radius-bottomright -moz-border-radius-topleft -moz-border-radius-topright -moz-border-right-colors -moz-border-start -moz-border-start-color -moz-border-start-style -moz-border-start-width -moz-border-top-colors -moz-box-align -moz-box-direction -moz-box-flex -moz-box-flex-group -moz-box-flexgroup -moz-box-ordinal-group -moz-box-orient -moz-box-pack -moz-box-shadow -moz-box-sizing -moz-column-count -moz-column-gap -moz-column-rule -moz-column-rule-color -moz-column-rule-style -moz-column-rule-width -moz-column-width -moz-context-properties -moz-float-edge -moz-force-broken-image-icon -moz-image-region -moz-linear-gradient -moz-margin-end -moz-margin-start -moz-opacity -moz-outline -moz-outline-color -moz-outline-offset -moz-outline-radius -moz-outline-radius-bottomleft -moz-outline-radius-bottomright -moz-outline-radius-topleft -moz-outline-radius-topright -moz-outline-style -moz-outline-width -moz-padding-end -moz-padding-start -moz-radial-gradient -moz-stack-sizing -moz-text-decoration-color -moz-text-decoration-line -moz-text-decoration-style -moz-transform -moz-transform-origin -moz-transition -moz-transition-delay -moz-transition-duration -moz-transition-property -moz-transition-timing-function -moz-user-focus -moz-user-input -moz-user-modify -moz-user-select -moz-window-shadow -ms-filter -ms-transform -ms-transform-origin -o-transform -webkit-animation -webkit-animation-delay -webkit-animation-direction -webkit-animation-duration -webkit-animation-fill-mode -webkit-animation-iteration-count -webkit-animation-name -webkit-animation-play-state -webkit-animation-timing-function -webkit-appearance -webkit-backface-visibility -webkit-background-clip -webkit-background-composite -webkit-background-origin -webkit-background-size -webkit-border-bottom-left-radius -webkit-border-bottom-right-radius -webkit-border-horizontal-spacing -webkit-border-image -webkit-border-radius -webkit-border-top-left-radius -webkit-border-top-right-radius -webkit-border-vertical-spacing -webkit-box-align -webkit-box-direction -webkit-box-flex -webkit-box-flex-group -webkit-box-lines -webkit-box-ordinal-group -webkit-box-orient -webkit-box-pack -webkit-box-reflect -webkit-box-shadow -webkit-box-sizing -webkit-column-break-after -webkit-column-break-before -webkit-column-break-inside -webkit-column-count -webkit-column-gap -webkit-column-rule -webkit-column-rule-color -webkit-column-rule-style -webkit-column-rule-width -webkit-column-width -webkit-columns -webkit-dashboard-region -webkit-font-smoothing -webkit-gradient -webkit-line-break -webkit-linear-gradient -webkit-margin-bottom-collapse -webkit-margin-collapse -webkit-margin-start -webkit-margin-top-collapse -webkit-marquee -webkit-marquee-direction -webkit-marquee-increment -webkit-marquee-repetition -webkit-marquee-speed -webkit-marquee-style -webkit-mask -webkit-mask-attachment -webkit-mask-box-image -webkit-mask-clip -webkit-mask-composite -webkit-mask-image -webkit-mask-origin -webkit-mask-position -webkit-mask-position-x -webkit-mask-position-y -webkit-mask-repeat -webkit-mask-size -webkit-nbsp-mode -webkit-padding-start -webkit-perspective -webkit-perspective-origin -webkit-radial-gradient -webkit-rtl-ordering -webkit-tap-highlight-color -webkit-text-fill-color -webkit-text-security -webkit-text-size-adjust -webkit-text-stroke -webkit-text-stroke-color -webkit-text-stroke-width -webkit-touch-callout -webkit-transform -webkit-transform-origin -webkit-transform-origin-x -webkit-transform-origin-y -webkit-transform-origin-z -webkit-transform-style -webkit-transition -webkit-transition-delay -webkit-transition-duration -webkit-transition-property -webkit-transition-timing-function -webkit-user-drag -webkit-user-modify -webkit-user-select align-content align-items align-self alignment-adjust alignment-baseline all animation animation-delay animation-direction animation-duration animation-fill-mode animation-iteration-count animation-name animation-play-state animation-timing-function appearance azimuth backface-visibility background background-attachment background-blend-mode background-break background-clip background-color background-image background-origin background-position background-position-x background-position-y background-repeat background-size baseline-shift binding bleed block-size bookmark-label bookmark-level bookmark-state bookmark-target border border-block border-block-end border-block-start border-bottom border-bottom-color border-bottom-left-radius border-bottom-right-radius border-bottom-style border-bottom-width border-collapse border-color border-image border-image-outset border-image-repeat border-image-slice border-image-source border-image-width border-inline border-inline-end border-inline-end-width border-inline-start border-inline-start-color border-inline-start-style border-inline-start-width border-left border-left-color border-left-style border-left-width border-radius border-right border-right-color border-right-style border-right-width border-spacing border-style border-top border-top-color border-top-left-radius border-top-right-radius border-top-style border-top-width border-width bottom box-align box-decoration-break box-direction box-flex box-flex-group box-lines box-ordinal-group box-orient box-pack box-shadow box-sizing break-after break-before break-inside caption-side caret-color clear clip color color-profile column-count column-fill column-gap column-rule column-rule-color column-rule-style column-rule-width column-span column-width columns content counter-increment counter-reset crop cue cue-after cue-before cursor direction display dominant-baseline drop-initial-after-adjust drop-initial-after-align drop-initial-before-adjust drop-initial-before-align drop-initial-size drop-initial-value elevation empty-cells fill fill-opacity filter fit fit-position flex flex-basis flex-direction flex-flow flex-grow flex-shrink flex-wrap float float-offset font font-effect font-emphasize font-family font-size font-size-adjust font-stretch font-style font-variant font-variant-ligatures font-weight gap grid-area grid-auto-flow grid-auto-rows grid-column grid-column-end grid-column-gap grid-column-start grid-columns grid-gap grid-row grid-row-gap grid-rows grid-template-areas grid-template-columns grid-template-rows hanging-punctuation height hyphenate-after hyphenate-before hyphenate-character hyphenate-lines hyphenate-resource hyphens icon image-orientation image-rendering image-resolution inline-box-align inline-size inset inset-inline-end inset-inline-start justify-content justify-items justify-self left letter-spacing line-height line-stacking line-stacking-ruby line-stacking-shift line-stacking-strategy list-style list-style-image list-style-position list-style-type margin margin-block margin-block-end margin-block-start margin-bottom margin-inline margin-inline-end margin-inline-start margin-left margin-right margin-top mark mark-after mark-before marker-offset marks marquee-direction marquee-play-count marquee-speed marquee-style mask mask-clip mask-image mask-origin mask-position mask-position-x mask-repeat mask-size max-height max-width min-block-size min-height min-inline-size min-width mix-blend-mode move-to nav-down nav-index nav-left nav-right nav-up object-fit opacity order orphans outline outline-color outline-offset outline-style outline-width overflow overflow-anchor overflow-style overflow-wrap overflow-x overflow-y padding padding-block padding-block-end padding-block-start padding-bottom padding-inline padding-inline-end padding-inline-start padding-left padding-right padding-top page page-break-after page-break-before page-break-inside page-policy paint-order pause pause-after pause-before perspective perspective-origin phonemes pitch pitch-range play-during pointer-events position presentation-level punctuation-trim quotes rendering-intent resize rest rest-after rest-before richness right rotation rotation-point ruby-align ruby-overhang ruby-position ruby-span scrollbar-color size speak speak-header speak-numeral speak-punctuation speech-rate stress string-set stroke stroke-dasharray stroke-linejoin stroke-opacity stroke-width tab-size table-layout target target-name target-new target-position text-align text-align-last text-anchor text-decoration text-decoration-color text-decoration-line text-decoration-style text-emphasis text-height text-indent text-justify text-outline text-overflow text-rendering text-shadow text-transform text-wrap top transform transform-origin transform-style transition transition-delay transition-duration transition-property transition-timing-function unicode-bidi user-select vector-effect vertical-align visibility voice-balance voice-duration voice-family voice-pitch voice-pitch-range voice-rate voice-stress voice-volume volume white-space white-space-collapse widows width will-change word-break word-spacing word-wrap z-index", + [1] = "active after before check checked disabled empty enabled first first-child first-letter first-line first-of-type focus hover indeterminate invalid lang last-child last-of-type left link not nth-child nth-last-child nth-of-type nth-last-of-type only-child only-of-type optional read-only read-write required right root selection target valid visited", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["TAG"] = { + id = 1, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["CLASS"] = { + id = 2, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["PSEUDOCLASS"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["UNKNOWN_PSEUDOCLASS"] = { + id = 4, + fgColor = rgb(0xFF8080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 6, + fgColor = rgb(0x8080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["UNKNOWN_IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["VALUE"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 9, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["ID"] = { + id = 10, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IMPORTANT"] = { + id = 11, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DIRECTIVE"] = { + id = 12, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/smalltalk.lua b/src/NotepadNext/languages/smalltalk.lua new file mode 100644 index 000000000..714f994b3 --- /dev/null +++ b/src/NotepadNext/languages/smalltalk.lua @@ -0,0 +1,104 @@ +local L = {} + +L.lexer = "smalltalk" + +L.extensions = { + "st", +} + +L.keywords = { + [0] = "ifTrue: ifFalse: whileTrue: whileFalse: ifNil: ifNotNil: whileTrue whileFalse repeat isNil notNil", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 1, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 3, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["SYMBOL"] = { + id = 4, + fgColor = rgb(0x408080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["BINARY"] = { + id = 5, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + }, + ["BOOL"] = { + id = 6, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["SELF"] = { + id = 7, + fgColor = rgb(0x8080FF), + bgColor = rgb(0xFFFFCC), + fontStyle = 1, + }, + ["SUPER"] = { + id = 8, + fgColor = rgb(0x0080FF), + bgColor = rgb(0xECFFEA), + fontStyle = 1, + }, + ["NIL"] = { + id = 9, + fgColor = rgb(0x8080C0), + bgColor = rgb(defaultBg), + }, + ["GLOBAL"] = { + id = 10, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["RETURN"] = { + id = 11, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SPECIAL"] = { + id = 12, + fgColor = rgb(0x808000), + bgColor = rgb(defaultBg), + }, + ["KWS END"] = { + id = 13, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + }, + ["ASSIGN"] = { + id = 14, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 15, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["SPECIAL SELECTOR"] = { + id = 16, + fgColor = rgb(0xFF80C0), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/spice.lua b/src/NotepadNext/languages/spice.lua new file mode 100644 index 000000000..9ac4788d4 --- /dev/null +++ b/src/NotepadNext/languages/spice.lua @@ -0,0 +1,67 @@ +local L = {} + +L.lexer = "spice" + +L.singleLineComment = "* " + +L.extensions = { + "scp", + "out", +} + +L.keywords = { + [0] = "ac alias alter alterparam append askvalues assertvalid autoscale break compose copy copytodoc dc delete destroy destroyvec diff display disto dowhile echo else end errorstop fftinit filter foreach fourier freqtotime function functionundef goto homecursors if isdisplayed label let linearize listing load loadaccumulator makelabel movelabel makesmithplot movecursorleft movecursorright msgbox nameplot newplot nextparam noise nopoints op plot plotf plotref poly print printcursors printevent printname printplot printstatus printtext printtol printunits printval printvector pwl pz quit removesmithplot rename repeat resume rotate runs rusage save sendplot sendscript sens set setcursor setdoc setlabel setlabeltype setmargins setnthtrigger setunits setvec setparam setplot setquery setscaletype settracecolor settracestyle setsource settrigger setvec setxlimits setylimits show showmod sort status step stop switch tf timetofreq timetowave tran unalias unlet unset unalterparam update version view wavefilter wavetotime where while write", + [1] = "abs askvalue atan average ceil cos db differentiate differentiatex exp finalvalue floor getcursorx getcursory getcursory0 getcursory1 getparam im ln initialvalue integrate integratex interpolate isdef isdisplayed j log length mag, max maxscale mean meanpts min minscale nextplot nextvector norm operatingpoint ph phase phaseextend pk_pk pos pulse re rms rmspts rnd sameplot sin sqrt stddev stddevpts tan tfall tolerance trise unitvec vector", + [2] = "param nodeset include options dcconv subckt ends model", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIERS"] = { + id = 1, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["KEYWORD"] = { + id = 2, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + }, + ["KEYWORD2"] = { + id = 3, + fgColor = rgb(0x00007F), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD3"] = { + id = 4, + fgColor = rgb(0x0040E0), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 5, + fgColor = rgb(0x007F7F), + bgColor = rgb(defaultBg), + }, + ["OPERATORS (DELIMITERS)"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VALUE"] = { + id = 7, + fgColor = rgb(0x7F007F), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 8, + fgColor = rgb(0x007F00), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/sql.lua b/src/NotepadNext/languages/sql.lua new file mode 100644 index 000000000..ec9985f4c --- /dev/null +++ b/src/NotepadNext/languages/sql.lua @@ -0,0 +1,87 @@ +local L = {} + +L.lexer = "sql" + +L.singleLineComment = "-- " + +L.extensions = { + "sql", +} + +L.keywords = { + [0] = "abs absolute access acos action add add_months adddate admin after aggregate all allocate alter and any app_name applock_mode applock_test are array as asc ascii asin assemblyproperty assertion asymkey_id at atan atn2 audit authid authorization autonomous_transaction avg backup before begin benchmark between bfilename bin binary_checksum bit_and bit_count bit_or body both breadth break browse bulk by call cascade cascaded case cast catalog catch ceil ceiling cert_id certproperty character charindex chartorowid check checkpoint checksum checksum_agg chr class clause close cluster clustered coalesce col_length col_name collate collation collect column columnproperty columns_updated comment commit completion compress compute concat concat_ws connect connection connectionproperty constant constraint constraints constructorcreate contains containsable containstable context_info continue conv convert corr corresponding cos cot count count_big covar_pop covar_samp create cross cube cume_dist current current_date current_path current_request_id current_role current_time current_timestamp current_user currval cursor_status cycle data database database_principal_id databasepropertyex datalength date_add date_format date_sub dateadd datediff datefirst dateformat datename datepart db_id db_name dbcc deallocate declare decode decryptbyasmkey decryptbycert decryptbykey decryptbykeyautocert decryptbypassphrase default deferrable deferred degrees delete dense_rank deny depth deref desc describe descriptor destroy destructor deterministic diagnostics dictionary difference disconnect disk distinct distributed do domain drop dump dynamic each else elsif empth encode encrypt encryptbyasmkey encryptbycert encryptbykey encryptbypassphrase end end-exec equals errlvl error_line error_message error_number error_procedure error_severity error_state escape eventdata every except exception exclusive exec execute exists exit exp export_set extends external extract false fetch file file_id file_idex file_name filegroup_id filegroup_name filegroupproperty fileproperty fillfactor first first_value floor fn_virtualfilestats for forall foreign format formatmessage found freetext freetexttable from from_days full fulltextcatalog fulltextcatalogproperty fulltextservice fulltextserviceproperty function general get get_filestream_transaction_context get_lock getansinull getdate getutcdate global go goto grant greatest group grouping grouping_id has_perms_by_name hashbytes having heap hex hextoraw holdlock host host_id host_name hour ident_current ident_incr ident_seed identified identity identity_insert identitycol if ifnull ignore immediate in include increment index index_col indexkey_property indexproperty indicator initcap initial initialize initially inner inout input insert instr instrb interface intersect into is is_member is_null is_numeric is_srvrolemember isdate isnull isnumeric isolation iterate java join key key_guid key_id kill lag language large last last_day last_value lateral lcase lead leading least left len length lengthb less level like limit limited lineno ln load local localtime localtimestamp locator lock log log10 loop lower lpad ltrim make_ref map match max maxextents merge mid min min_active_rowversion minus minute mlslabel mod mode modifies modify module month months_between names national natural naturaln new new_time newid newsequentialid next next_day nextval no noaudit nocheck nocompress nocopy nonclustered none not nowait ntile null nullif number_base nvl nvl2 object object_definition object_id object_name object_property object_schema_name objectproperty objectpropertyex ocirowid oct of off offline offsets old on online only opaque open opendatasource openquery openrowset openxml operation operator option or ord order ordinalityorganization original_db_name original_login others out outer output over package pad parameter parameters parsename partial partition path pathname patindex pctfree percent percent_rank permissions pi pivot plan pls_integer positive positiven postfix pow power pragma prefix preorder prepare preserve primary print prior private privileges proc procedure public publishingservername pwdcompare pwdencrypt quotename radians raise raiserror rand range rank ratio_to_export rawtohex read reads readtext reconfigure record recursive ref references referencing reftohex relative release release_lock rename repeat replace replicate replication resource restore restrict result return returns reverse revert revoke right rollback rollup round routine row row_number rowcount rowcount_big rowguidcol rowidtochar rowlabel rownum rows rowtype rpad rtrim rule save savepoint schema schema_id schema_name scope scope_identity scroll search second section securityaudit seddev_samp select separate sequence serverproperty session session_user set sets setuser share shutdown sign signbyasymkey signbycert sin sinh size some soundex sp_helplanguage space specific specifictype sql sql_variant_property sqlcode sqlerrm sqlexception sqlstate sqlwarning sqrt square start state statement static statistics stats_date std stddev stdev stdev_pop stdevp str strcmp structure stuff subdate substr substrb substring substring_index subtype successful sum suser_id suser_name suser_sid suser_sname switchoffset synonym sys_context sys_guid sysdate sysdatetime sysdatetimeoffset system_user sysutcdatetime table tablesample tan tanh temporary terminate textptr textsize textvalid than then timezone_abbr timezone_hour timezone_minute timezone_region to to_char to_date to_days to_number to_single_byte todatetimeoffset top trailing tran transaction translate translation treat trigger trigger_nestlevel trim true trunc truncate try tsequal type type_id type_name typeproperty ucase uid under unicode union unique unknown unnest unpivot update updatetext upper usage use user user_id user_name userenv using validate value values var var_pop var_samp variable variance varp varying verifysignedbyasmkey verifysignedbycert view vsize waitfor when whenever where while with without work write writetext xact_state zone", + [1] = "None", + [4] = "bfile bigint binary binary_integer bit blob bool boolean char char_base clob cursor date datetime datetime2 datetimeoffset day dec decimal double enum float hierarchyid image int integer interval long longblob longtext mediumblob mediumint mediumtext money nchar nclob ntext number numeric nvarchar precision raw real rowid smalldatetime smallint smallmoney sql_variant text time timestamp tinyblob tinyint tinytext uniqueidentifier urowid varbinary varchar varchar2 xml year", +} + +L.styles = { + ["KEYWORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["USER1"] = { + id = 16, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD2"] = { + id = 19, + fgColor = rgb(0x800080), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["STRING2"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["Q OPERATOR"] = { + id = 24, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["WHITE SPACE"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/srec.lua b/src/NotepadNext/languages/srec.lua new file mode 100644 index 000000000..76570c944 --- /dev/null +++ b/src/NotepadNext/languages/srec.lua @@ -0,0 +1,112 @@ +local L = {} + +L.lexer = "srec" + +L.singleLineComment = "# " + +L.extensions = { + "mot", + "srec", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["RECSTART"] = { + id = 1, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["RECTYPE"] = { + id = 2, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["RECTYPE_UNKNOWN"] = { + id = 3, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["BYTECOUNT"] = { + id = 4, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["BYTECOUNT_WRONG"] = { + id = 5, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["NOADDRESS"] = { + id = 6, + fgColor = rgb(0x7F00FF), + bgColor = rgb(defaultBg), + }, + ["DATAADDRESS"] = { + id = 7, + fgColor = rgb(0x007FFF), + bgColor = rgb(defaultBg), + }, + ["RECCOUNT"] = { + id = 8, + fgColor = rgb(0x7F00FF), + bgColor = rgb(defaultBg), + }, + ["STARTADDRESS"] = { + id = 9, + fgColor = rgb(0x007FFF), + bgColor = rgb(defaultBg), + }, + ["ADDRESSFIELD_UNKNOWN"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["DATA_ODD"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DATA_EVEN"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["DATA_UNKNOWN"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["DATA_EMPTY"] = { + id = 15, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CHECKSUM"] = { + id = 16, + fgColor = rgb(0x00BF00), + bgColor = rgb(defaultBg), + }, + ["CHECKSUM_WRONG"] = { + id = 17, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["GARBAGE"] = { + id = 18, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, +} +return L diff --git a/src/NotepadNext/languages/swift.lua b/src/NotepadNext/languages/swift.lua new file mode 100644 index 000000000..6150afa20 --- /dev/null +++ b/src/NotepadNext/languages/swift.lua @@ -0,0 +1,113 @@ +local L = {} + +L.lexer = "swift" + +L.singleLineComment = "// " + +L.extensions = { + "swift", +} + +L.keywords = { + [0] = "class deinit enum extension func import init internal let operator private protocol public static struct subscript typealias var keywordclass.swift.statements=break case continue default do else fallthrough for if in return switch where while", + [2] = "as dynamicType false is nil self Self super true __COLUMN__ __FILE__ __FUNCTION__ __LINE__", + [3] = "associativity convenience dynamic didSet final get infix inout lazy left mutating none nonmutating optional override postfix precedence prefix Protocol required right set Type unowned weak willSet", +} + +L.styles = { + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DEFAULT"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 16, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["VERBATIM"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["REGEX"] = { + id = 14, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE DOC"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["COMMENT DOC KEYWORD"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT DOC KEYWORD ERROR"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT"] = { + id = 23, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR COMMENT DOC"] = { + id = 24, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/tcl.lua b/src/NotepadNext/languages/tcl.lua new file mode 100644 index 000000000..d58b8cbe4 --- /dev/null +++ b/src/NotepadNext/languages/tcl.lua @@ -0,0 +1,105 @@ +local L = {} + +L.lexer = "tcl" + +L.singleLineComment = "# " + +L.extensions = { + "tcl", +} + +L.keywords = { + [0] = "after append apply array auto_execok auto_import auto_load auto_load_index auto_qualify auto_reset bgerror binary break catch cd chan clock close concat continue coroutine dde dict default else elseif encoding env eof error eval exec exit expr fblocked fconfigure fcopy file fileevent filename flush for foreach format gets glob global history http if incr info interp join lappend lassign lindex linsert list llength lmap load lrange lrepeat lreplace lreverse lsearch lset lsort memory my namespace next nextto oo::class oo::copy oo::define oo::objdefine oo::object open package parray pid pkg_mkIndex platform proc puts pwd read regexp registry regsub rename return scan seek self set socket source split string subst switch tailcall tclLog tclMacPkgSearch tclPkgSetup tclPkgUnknown tell throw time trace try unknown unload unset update uplevel upvar variable vwait while yield yeildto zlib", + [1] = "bell bind bindtags button canvas checkbutton console destroy entry event focus font frame grab grid image label labelframe listbox lower menu menubutton message option pack panedwindow place radiobutton raise scale scrollbar selection send spinbox text tk tkerror tkwait toplevel ttk::button ttk::checkbutton ttk::combobox ttk::entry ttk::frame ttk::intro ttk::label ttk::labeframe ttk::menubutton ttk::notebook ttk::panedwindow ttk::progressbar ttk::radiobutton ttk::scale ttk::scrollbar ttk::sizegrip ttk::spinbox ttk::style winfo wm", + [2] = "@scope body class code common component configbody constructor define destructor hull import inherit itcl itk itk_component itk_initialize itk_interior itk_option iwidgets keep method private protected public", + [3] = "tkButtonDown tkButtonEnter tkButtonInvoke tkButtonLeave tkButtonUp tkCancelRepeat tkCheckRadioInvoke tkDarken tkEntryAutoScan tkEntryBackspace tkEntryButton1 tkEntryClosestGap tkEntryInsert tkEntryKeySelect tkEntryMouseSelect tkEntryNextWord tkEntryPaste tkEntryPreviousWord tkEntrySeeInsert tkEntrySetCursor tkEntryTranspose tkEventMotifBindings tkFDGetFileTypes tkFirstMenu tkFocusGroup_Destroy tkFocusGroup_In tkFocusGroup_Out tkFocusOK tkListboxAutoScan tkListboxBeginExtend tkListboxBeginSelect tkListboxBeginToggle tkListboxCancel tkListboxDataExtend tkListboxExtendUpDown tkListboxMotion tkListboxSelectAll tkListboxUpDown tkMbButtonUp tkMbEnter tkMbLeave tkMbMotion tkMbPost tkMenuButtonDown tkMenuDownArrow tkMenuDup tkMenuEscape tkMenuFind tkMenuFindName tkMenuFirstEntry tkMenuInvoke tkMenuLeave tkMenuLeftArrow tkMenuMotion tkMenuNextEntry tkMenuNextMenu tkMenuRightArrow tkMenuUnpost tkMenuUpArrow tkMessageBox tkPostOverPoint tkRecolorTree tkRestoreOldGrab tkSaveGrabInfo tkScaleActivate tkScaleButton2Down tkScaleButtonDown tkScaleControlPress tkScaleDrag tkScaleEndDrag tkScaleIncrement tkScreenChanged tkScrollButton2Down tkScrollButtonDown tkScrollButtonUp tkScrollByPages tkScrollByUnits tkScrollDrag tkScrollEndDrag tkScrollSelect tkScrollStartDrag tkScrollToPos tkScrollTopBottom tkTabToWindow tkTearOffMenu tkTextAutoScan tkTextButton1 tkTextClosestGap tkTextInsert tkTextKeyExtend tkTextKeySelect tkTextNextPara tkTextNextPos tkTextNextWord tkTextPaste tkTextPrevPara tkTextPrevPos tkTextResetAnchor tkTextScrollPages tkTextSelectTo tkTextSetCursor tkTextTranspose tkTextUpDownLine tkTraverseToMenu tkTraverseWithinMenu tk_bisque tk_chooseColor tk_dialog tk_focusFollowsMouse tk_focusNext tk_focusPrev tk_getOpenFile tk_getSaveFile tk_messageBox tk_optionMenu tk_popup tk_setPalette tk_textCopy tk_textCut tk_textPaste", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["MODIFIER"] = { + id = 10, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["EXPAND"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 12, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TYPE WORD"] = { + id = 13, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["SUB BRACE"] = { + id = 9, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["SUBSTITUTION"] = { + id = 8, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["WORD IN QUOTE"] = { + id = 4, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IN QUOTE"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT BOX"] = { + id = 17, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["BLOCK COMMENT"] = { + id = 18, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/tehex.lua b/src/NotepadNext/languages/tehex.lua new file mode 100644 index 000000000..9a3dde672 --- /dev/null +++ b/src/NotepadNext/languages/tehex.lua @@ -0,0 +1,88 @@ +local L = {} + +L.lexer = "tehex" + +L.extensions = { + "tek", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["RECSTART"] = { + id = 1, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["RECTYPE"] = { + id = 2, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + }, + ["RECTYPE_UNKNOWN"] = { + id = 3, + fgColor = rgb(0x7F0000), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["BYTECOUNT"] = { + id = 4, + fgColor = rgb(0x7F7F00), + bgColor = rgb(defaultBg), + }, + ["BYTECOUNT_WRONG"] = { + id = 5, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["DATAADDRESS"] = { + id = 7, + fgColor = rgb(0x007FFF), + bgColor = rgb(defaultBg), + }, + ["STARTADDRESS"] = { + id = 9, + fgColor = rgb(0x007FFF), + bgColor = rgb(defaultBg), + }, + ["ADDRESSFIELD_UNKNOWN"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["DATA_ODD"] = { + id = 12, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DATA_EVEN"] = { + id = 13, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["CHECKSUM"] = { + id = 16, + fgColor = rgb(0x00BF00), + bgColor = rgb(defaultBg), + }, + ["CHECKSUM_WRONG"] = { + id = 17, + fgColor = rgb(0xFFFF00), + bgColor = rgb(0xFF0000), + }, + ["GARBAGE"] = { + id = 18, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, +} +return L diff --git a/src/NotepadNext/languages/tex.lua b/src/NotepadNext/languages/tex.lua new file mode 100644 index 000000000..d4433de17 --- /dev/null +++ b/src/NotepadNext/languages/tex.lua @@ -0,0 +1,49 @@ +local L = {} + +L.lexer = "tex" + +L.singleLineComment = "% " + +L.extensions = { + "tex", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["SPECIAL"] = { + id = 1, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["GROUP"] = { + id = 2, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SYMBOL"] = { + id = 3, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["COMMAND"] = { + id = 4, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TEXT"] = { + id = 5, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/text.lua b/src/NotepadNext/languages/text.lua new file mode 100644 index 000000000..c88a36b30 --- /dev/null +++ b/src/NotepadNext/languages/text.lua @@ -0,0 +1,23 @@ +local L = {} + +L.name = "Text" + +L.lexer = "null" + +L.disableFoldMargin = true + +L.extensions = { + "", + "txt", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 0, + }, +} + +return L diff --git a/src/NotepadNext/languages/txt2tags.lua b/src/NotepadNext/languages/txt2tags.lua new file mode 100644 index 000000000..a329a23f4 --- /dev/null +++ b/src/NotepadNext/languages/txt2tags.lua @@ -0,0 +1,156 @@ +local L = {} + +L.lexer = "txt2tags" + +L.singleLineComment = "! " + +L.extensions = { + "t2t", +} + +L.keywords = { +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["SPECIAL"] = { + id = 1, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["STRONG"] = { + id = 2, + fgColor = rgb(0x445675), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STRONG 2 (NOT USED)"] = { + id = 3, + fgColor = rgb(0x445675), + bgColor = rgb(defaultBg), + }, + ["EM1 (ITALIC)"] = { + id = 4, + fgColor = rgb(0x653A39), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["EM2 (UNDERLINE)"] = { + id = 5, + fgColor = rgb(0x386742), + bgColor = rgb(defaultBg), + }, + ["H1"] = { + id = 6, + fgColor = rgb(0xE20700), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["H2"] = { + id = 7, + fgColor = rgb(0xE20700), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["H3"] = { + id = 8, + fgColor = rgb(0xA81D05), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["H4"] = { + id = 9, + fgColor = rgb(0x871704), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["H5"] = { + id = 10, + fgColor = rgb(0x871704), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["H6"] = { + id = 11, + fgColor = rgb(0x871704), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["PRECHAR (NOT USED)"] = { + id = 12, + fgColor = rgb(0x871704), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["ULIST"] = { + id = 13, + fgColor = rgb(0xE300EE), + bgColor = rgb(defaultBg), + }, + ["OLIST"] = { + id = 14, + fgColor = rgb(0xE300EE), + bgColor = rgb(defaultBg), + }, + ["BLOCKQUOTE"] = { + id = 15, + fgColor = rgb(0x015F52), + bgColor = rgb(defaultBg), + }, + ["STRIKEOUT"] = { + id = 16, + fgColor = rgb(0x644A9B), + bgColor = rgb(defaultBg), + }, + ["HRULE"] = { + id = 17, + fgColor = rgb(0xff901e), + bgColor = rgb(defaultBg), + }, + ["LINK"] = { + id = 18, + fgColor = rgb(0x0930DE), + bgColor = rgb(defaultBg), + fontStyle = 2, + }, + ["CODE"] = { + id = 19, + fgColor = rgb(0x009f00), + bgColor = rgb(defaultBg), + }, + ["CODE2"] = { + id = 20, + fgColor = rgb(0x009f00), + bgColor = rgb(defaultBg), + }, + ["CODEBLOCK"] = { + id = 21, + fgColor = rgb(0x005f00), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 22, + fgColor = rgb(0x777777), + bgColor = rgb(defaultBg), + }, + ["OPTION"] = { + id = 23, + fgColor = rgb(0xC0036E), + bgColor = rgb(defaultBg), + }, + ["PREPROC"] = { + id = 24, + fgColor = rgb(0x848B00), + bgColor = rgb(defaultBg), + }, + ["POSTPROC"] = { + id = 25, + fgColor = rgb(0xC05600), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/vb.lua b/src/NotepadNext/languages/vb.lua new file mode 100644 index 000000000..0c85e9590 --- /dev/null +++ b/src/NotepadNext/languages/vb.lua @@ -0,0 +1,60 @@ +local L = {} + +L.lexer = "vb" + +L.singleLineComment = "' " + +L.extensions = { + "vb", + "vbs", +} + +L.keywords = { + [0] = "addhandler addressof alias and andalso as boolean by byref byte byval call case catch cbool cbyte cchar cdate cdbl cdec char cint class clng cobj const continue csbyte cshort csng cstr ctype cuint culng cushort date decimal declare default delegate dim directcast do double each else elseif end endif enum erase error event exit false finally for friend function get gettype global gosub goto handles if implements imports in inherits integer interface is isnot let lib like long loop me mod module mustinherit mustoverride mybase myclass namespace narrowing new next not nothing notinheritable notoverridable object of on operator option optional or orelse out overloads overridable overrides paramarray partial private property protected public raiseevent readonly redim rem removehandler resume return sbyte select set shadows shared short single static step stop strict string structure sub synclock then throw to true try trycast typeof uinteger ulong ushort using variant wend when while widening with withevents writeonly xor attribute begin currency implement load lset rset type unload aggregate ansi assembly async auto await binary compare custom distinct equals explicit from group into isfalse istrue iterator join key mid off order preserve skip take text unicode until where yield", +} + +L.styles = { + ["DEFAULT"] = { + id = 7, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 2, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["WORD"] = { + id = 3, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 4, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 5, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["DATE"] = { + id = 8, + fgColor = rgb(0x00FF00), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/verilog.lua b/src/NotepadNext/languages/verilog.lua new file mode 100644 index 000000000..1045c61ce --- /dev/null +++ b/src/NotepadNext/languages/verilog.lua @@ -0,0 +1,88 @@ +local L = {} + +L.lexer = "verilog" + +L.singleLineComment = "// " + +L.extensions = { + "v", + "sv", + "vh", + "svh", +} + +L.keywords = { + [0] = "accept_on alias always always_comb always_ff always_latch and assert assign assume attribute automatic before begin bind bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable dist do edge else end endattribute endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup endinterface endmodule endpackage endprimitive endprogram endproperty endsequence endspecify endtable endtask enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import incdir include initial inout input inside instance int integer interconnect interface intersect join join_any join_none large let liblist library local localparam logic longint macromodule matches medium modport module nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 scalared sequence shortint shortreal showcancelled signed small soft solve specify specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on s_always s_eventually s_nexttime s_until s_until_with table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior trireg type typedef union unique unique0 unsigned until until_with untyped use var vectored virtual void wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor", + [1] = "$acos $acosh $asin $asinh $assertcontrol $assertkill $assertoff $asserton $assertpasson $assertpassoff $assertfailon $assertfailoff $assertnonvacuouson $assertvacuousoff $async$and$array $async$and$plane $async$nand$array $async$nand$plane $async$nor$array $async$nor$plane $async$or$array $async$or$plane $atan $atan2 $atanh $bits $bitstoreal $bitstoshortreal $cast $ceil $changed_gclk $changing_gclk $clog2 $comment $cos $cosh $countdrivers $countones $coverage_control $coverage_get $coverage_get_max $coverage_merge $coverage_save $date $dimensions $display $displayb $displayh $displayo $dist_chi_square $dist_erlang $dist_exponential $dist_normal $dist_poisson $dist_t $dist_uniform $dumpall $dumpfile $dumpflush $dumplimit $dumpoff $dumpon $dumpportsall $dumpportsflush $dumpportslimit $dumpportsoff $dumpportson $dumpvars $end $enddefinitions $error $exit $exp $falling_gclk $fatal $fclose $fdisplay $fdisplayb $fdisplayh $fdisplayo $fell $fell_gclk $feof $ferror $fflush $fgetc $fgets $finish $floor $fmonitor $fmonitorb $fmonitorh $fmonitoro $fopen $fread $fscanf $fseek $fstrobe $ftell $fullskew $future_gclk $fwrite $fwriteb $fwriteh $fwriteo $getpattern $get_coverage $high $history $hold $hypot $increment $incsave $info $input $isunbounded $isunknown $itor $key $left $list $ln $load_coverage_db $log $log10 $low $monitor $monitorb $monitorh $monitoro $monitoroff $monitoron $nochange $nokey $nolog $onehot $onehot0 $past $past_gclk $period $pow $printtimescale $q_add $q_exam $q_full $q_initialize $q_remove $random $readmemb $readmemh $realtime $realtobits $recovery $recrem $removal $reset $reset_count $reset_value $restart $rewind $right $rising_gclk $root $rose $rose_gclk $rtoi $sampled $save $scale $scope $setup $setuphold $set_coverage_db_name $sformat $sformatf $shortrealtobits $showscopes $showvariables $showvars $signed $sin $sinh $size $skew $sqrt $sreadmemb $sreadmemh $sscanf $stable $stable_gclk $steady_gclk $stime $stop $strobe $strobeb $strobeh $strobeo $swrite $sync$and$array $sync$and$plane $sync$nand$array $sync$nand$plane $sync$nor$array $sync$nor$plane $sync$or$array $sync$or$plane $system $tan $tanh $test$plusargs $time $timeformat $timescale $timeskew $typename $typeof $uandom $ungetc $unit $unpacked_dimensions $unsigned $upscope $urandom_range $value$plusargs $var $vcdclose $version $warning $width $write $writeb $writeh $writememb $writememh $writeo", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 11, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["TAGNAME"] = { + id = 2, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 5, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["KEYWORD"] = { + id = 7, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 10, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["PREPROCESSOR"] = { + id = 9, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 6, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE BANG"] = { + id = 3, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["USER"] = { + id = 19, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/vhdl.lua b/src/NotepadNext/languages/vhdl.lua new file mode 100644 index 000000000..8af02b216 --- /dev/null +++ b/src/NotepadNext/languages/vhdl.lua @@ -0,0 +1,103 @@ +local L = {} + +L.lexer = "vhdl" + +L.singleLineComment = "-- " + +L.extensions = { + "vhd", + "vhdl", +} + +L.keywords = { + [0] = "access after alias all architecture array assert attribute begin block body buffer bus case case? converse component configuration constant designated_subtype disconnect downto else elsif end entity exit file for force function generate generic group guarded if impure in index inertial inout is label library linkage literal loop map new next null of on open others out package port postponed procedure process pure range record register reject report return select severity shared signal subtype then to transport type unaffected units until use variable wait when while with assume assume_guarantee context cover default fairness force parameter privat property protect protected record reflect release restrict restrict_guarantee sequence strong value view vmode vprop vunit", + [1] = "abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor", + [2] = "left right low high ascending image value pos val succ pred leftof rightof base range reverse_range length delayed stable quiet transaction event active last_event last_active last_value driving driving_value simple_name path_name instance_name minimum maximum", + [3] = "now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left rotate_right resize to_integer to_unsigned to_signed to_string to_bstring to_binarystring to_ostring to_octalstring to_hstring to_hexstring std_match to_01", + [4] = "std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives vital_timing", + [5] = "boolean boolean_vector bit character severity_level integer integer_vector real real_vector time time_vector delay_length natural positive string bit_vector file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic std_logic_vector X01 X01Z UX01 UX01Z unsigned signed", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LIne"] = { + id = 2, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE BANG"] = { + id = 15, + fgColor = rgb(0x008080), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 3, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 4, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 5, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["IDENTIFIER"] = { + id = 6, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION"] = { + id = 8, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STD OPERATOR"] = { + id = 9, + fgColor = rgb(0x0080C0), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["ATTRIBUTE"] = { + id = 10, + fgColor = rgb(0x8080FF), + bgColor = rgb(0xFFFFCC), + fontStyle = 1, + }, + ["STD FUNCTION"] = { + id = 11, + fgColor = rgb(0x0080FF), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["STD PACKAGE"] = { + id = 12, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["STD TYPE"] = { + id = 13, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + }, + ["USER DEFINE"] = { + id = 14, + fgColor = rgb(0xB5E71F), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/languages/visualprolog.lua b/src/NotepadNext/languages/visualprolog.lua new file mode 100644 index 000000000..67547b797 --- /dev/null +++ b/src/NotepadNext/languages/visualprolog.lua @@ -0,0 +1,139 @@ +local L = {} + +L.lexer = "visualprolog" + +L.singleLineComment = "% " + +L.extensions = { + "pro", + "cl", + "i", + "pack", + "ph", +} + +L.keywords = { + [0] = "goal namespace interface class implement open inherits supports resolve delegate monitor constants domains predicates constructors properties clauses facts", + [1] = "guard language stdcall apicall c thiscall prolog digits if then elseif else foreach do try catch finally erroneous failure procedure determ multi nondeterm anyflow and or externally from div mod rem quot in orelse otherwise", + [2] = "include bininclude requires orrequires if then else elseif endif error message export externally options", + [3] = "short detail end exception withdomain", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["MAJOR"] = { + id = 1, + fgColor = rgb(0x808000), + bgColor = rgb(defaultBg), + }, + ["MINOR"] = { + id = 2, + fgColor = rgb(0x333399), + bgColor = rgb(defaultBg), + }, + ["DIRECTIVE"] = { + id = 3, + fgColor = rgb(0x800080), + bgColor = rgb(defaultBg), + }, + ["COMMENT BLOCK"] = { + id = 4, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["COMMENT LINE"] = { + id = 5, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["COMMENT KEY"] = { + id = 6, + fgColor = rgb(0x8050A0), + bgColor = rgb(defaultBg), + }, + ["COMMENT KEY ERROR"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 8, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["VARIABLE"] = { + id = 9, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["ANONYMOUS"] = { + id = 10, + fgColor = rgb(0xA0A0C0), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 11, + fgColor = rgb(0x0000C0), + bgColor = rgb(defaultBg), + }, + ["OPERATOR"] = { + id = 12, + fgColor = rgb(0xA00000), + bgColor = rgb(defaultBg), + }, + ["CHARACTER"] = { + id = 13, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["CHARACTER TOO MANY"] = { + id = 14, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["CHARACTER ESCAPE ERROR"] = { + id = 15, + fgColor = rgb(0x800000), + bgColor = rgb(defaultBg), + }, + ["STRING"] = { + id = 16, + fgColor = rgb(0x3898B2), + bgColor = rgb(defaultBg), + }, + ["STRING ESCAPE"] = { + id = 17, + fgColor = rgb(0xFF8040), + bgColor = rgb(defaultBg), + }, + ["STRING ESCAPE ERROR"] = { + id = 18, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["STRING EOL OPEN"] = { + id = 19, + fgColor = rgb(defaultBg), + bgColor = rgb(0xFF4040), + }, + ["STRING VERBATIM"] = { + id = 20, + fgColor = rgb(0x8064A2), + bgColor = rgb(defaultBg), + }, + ["STRING VERBATIM SPECIAL"] = { + id = 21, + fgColor = rgb(0x800040), + bgColor = rgb(defaultBg), + }, + ["STRING VERBATIM EOL"] = { + id = 22, + fgColor = rgb(defaultBg), + bgColor = rgb(0xFF8000), + }, +} +return L diff --git a/src/NotepadNext/languages/xml.lua b/src/NotepadNext/languages/xml.lua new file mode 100644 index 000000000..f5ee08c83 --- /dev/null +++ b/src/NotepadNext/languages/xml.lua @@ -0,0 +1,125 @@ +local L = {} + +L.lexer = "xml" + +L.first_line = { + "^<%?xml" +} + +L.extensions = { + "xml", + "xaml", + "xsl", + "xslt", + "xsd", + "xul", + "kml", + "svg", + "mxml", + "xsml", + "wsdl", + "xlf", + "xliff", + "xbl", + "sxbl", + "sitemap", + "gml", + "gpx", + "plist", + "vcproj", + "vcxproj", + "csproj", + "csxproj", + "vbproj", + "dbproj", +} + +L.properties = { + ["fold.html"] = "1", +} + +L.keywords = { +} + +L.styles = { + ["XMLSTART"] = { + id = 12, + fgColor = rgb(0xFF0000), + bgColor = rgb(0xFFFF00), + }, + ["XMLEND"] = { + id = 13, + fgColor = rgb(0xFF0000), + bgColor = rgb(0xFFFF00), + }, + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 9, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["NUMBER"] = { + id = 5, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["DOUBLESTRING"] = { + id = 6, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["SINGLESTRING"] = { + id = 7, + fgColor = rgb(TypeColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["TAG"] = { + id = 1, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["TAGEND"] = { + id = 11, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["TAGUNKNOWN"] = { + id = 2, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["ATTRIBUTE"] = { + id = 3, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["ATTRIBUTEUNKNOWN"] = { + id = 4, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, + ["SGMLDEFAULT"] = { + id = 21, + fgColor = rgb(defaultFg), + bgColor = rgb(0xA6CAF0), + }, + ["CDATA"] = { + id = 17, + fgColor = rgb(0xFF8000), + bgColor = rgb(defaultBg), + }, + ["ENTITY"] = { + id = 10, + fgColor = rgb(defaultFg), + bgColor = rgb(0xFEFDE0), + fontStyle = 2, + }, +} +return L diff --git a/src/NotepadNext/languages/yaml.lua b/src/NotepadNext/languages/yaml.lua new file mode 100644 index 000000000..6767e382e --- /dev/null +++ b/src/NotepadNext/languages/yaml.lua @@ -0,0 +1,66 @@ +local L = {} + +L.lexer = "yaml" + +L.singleLineComment = "# " + +L.extensions = { + "yml", + "yaml", +} + +L.keywords = { + [0] = "true false yes no", +} + +L.styles = { + ["DEFAULT"] = { + id = 0, + fgColor = rgb(defaultFg), + bgColor = rgb(defaultBg), + }, + ["IDENTIFIER"] = { + id = 2, + fgColor = rgb(OperatorColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["COMMENT"] = { + id = 1, + fgColor = rgb(0x008000), + bgColor = rgb(defaultBg), + }, + ["INSTRUCTION WORD"] = { + id = 3, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["NUMBER"] = { + id = 4, + fgColor = rgb(0xFF8040), + bgColor = rgb(defaultBg), + }, + ["REFERENCE"] = { + id = 5, + fgColor = rgb(0x804000), + bgColor = rgb(defaultBg), + }, + ["DOCUMENT"] = { + id = 6, + fgColor = rgb(InstructionColor), + bgColor = rgb(defaultBg), + }, + ["TEXT"] = { + id = 7, + fgColor = rgb(0x808080), + bgColor = rgb(defaultBg), + fontStyle = 1, + }, + ["ERROR"] = { + id = 8, + fgColor = rgb(0xFF0000), + bgColor = rgb(defaultBg), + }, +} +return L diff --git a/src/NotepadNext/main.cpp b/src/NotepadNext/main.cpp new file mode 100644 index 000000000..43104ade6 --- /dev/null +++ b/src/NotepadNext/main.cpp @@ -0,0 +1,79 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + */ + + +#include <QDebug> +#include <QSettings> +#include <QSysInfo> +#include <QApplication> +#include <QDataStream> + +#include "NotepadNextApplication.h" + +int main(int argc, char *argv[]) +{ + qSetMessagePattern("[%{time process}] %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}: %{message}"); + + // Set these since other parts of the app references these + QApplication::setOrganizationName("NotepadNext"); + QApplication::setApplicationName("NotepadNext"); + QGuiApplication::setApplicationDisplayName("Notepad Next"); +#ifdef Q_OS_UNIX + // Unix doesn't provide an application version by default + QGuiApplication::setApplicationVersion(APP_VERSION); +#endif + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif + + // Default settings format + QSettings::setDefaultFormat(QSettings::IniFormat); + + NotepadNextApplication app(argc, argv); + + // Log some debug info + qInfo("============================="); + qInfo("%s v%s%s", qUtf8Printable(QApplication::applicationDisplayName()), qUtf8Printable(QApplication::applicationVersion()), APP_DISTRIBUTION); + qInfo("Build Date/Time: %s %s", __DATE__, __TIME__); + qInfo("Qt: %s", qVersion()); + qInfo("OS: %s", qUtf8Printable(QSysInfo::prettyProductName())); + qInfo("Locale: %s", qUtf8Printable(QLocale::system().name())); + qInfo("CPU: %s", qUtf8Printable(QSysInfo::currentCpuArchitecture())); + qInfo("File Path: %s", qUtf8Printable(QApplication::applicationFilePath())); + qInfo("Arguments: %s", qUtf8Printable(app.arguments().join(' '))); + qInfo("============================="); + + if(app.isPrimary()) { + app.init(); + + return app.exec(); + } + else { + qInfo() << "Primary instance already running. PID:" << app.primaryPid(); + + app.sendInfoToPrimaryInstance(); + + qInfo() << "Secondary instance closing..."; + + app.exit(0); + + return 0; + } +} diff --git a/src/NotepadNext/qdarkstyle/dark/rc/.keep b/src/NotepadNext/qdarkstyle/dark/rc/.keep new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/src/NotepadNext/qdarkstyle/dark/rc/.keep @@ -0,0 +1 @@ + diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down.png new file mode 100644 index 000000000..5575ab5ce Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down@2x.png new file mode 100644 index 000000000..4596a5ce8 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_disabled.png new file mode 100644 index 000000000..bdf8c1abb Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_disabled@2x.png new file mode 100644 index 000000000..dc1bcb524 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_focus.png new file mode 100644 index 000000000..94fcdc359 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_focus@2x.png new file mode 100644 index 000000000..2b12f74d0 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_pressed.png new file mode 100644 index 000000000..4058c58b3 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_pressed@2x.png new file mode 100644 index 000000000..d43b0affa Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_down_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left.png new file mode 100644 index 000000000..7fbc35065 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left@2x.png new file mode 100644 index 000000000..dc649ca70 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_disabled.png new file mode 100644 index 000000000..fa3b282cc Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_disabled@2x.png new file mode 100644 index 000000000..87c928ea3 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_focus.png new file mode 100644 index 000000000..52a0d9102 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_focus@2x.png new file mode 100644 index 000000000..0ee702924 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_pressed.png new file mode 100644 index 000000000..c04ce0943 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_pressed@2x.png new file mode 100644 index 000000000..02218c80d Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_left_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right.png new file mode 100644 index 000000000..fd31b4f2a Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right@2x.png new file mode 100644 index 000000000..4dbc93120 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_disabled.png new file mode 100644 index 000000000..bb4cdb036 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_disabled@2x.png new file mode 100644 index 000000000..50f173096 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_focus.png new file mode 100644 index 000000000..9dd8f0f0b Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_focus@2x.png new file mode 100644 index 000000000..1ac9d5c9e Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_pressed.png new file mode 100644 index 000000000..8ce10fcbe Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_pressed@2x.png new file mode 100644 index 000000000..86e3b9286 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_right_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up.png new file mode 100644 index 000000000..2ea571e47 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up@2x.png new file mode 100644 index 000000000..51b1d7234 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_disabled.png new file mode 100644 index 000000000..146b65f16 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_disabled@2x.png new file mode 100644 index 000000000..cacee7f74 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_focus.png new file mode 100644 index 000000000..ab33162c7 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_focus@2x.png new file mode 100644 index 000000000..0c8ef33f4 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_pressed.png new file mode 100644 index 000000000..c3368d096 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_pressed@2x.png new file mode 100644 index 000000000..a63819665 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/arrow_up_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_disabled.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_disabled@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_focus.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_focus@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_pressed.png new file mode 100644 index 000000000..1aeed5554 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/base_icon_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_pressed@2x.png new file mode 100644 index 000000000..f42fc6610 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/base_icon_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed.png new file mode 100644 index 000000000..d484c324b Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed@2x.png new file mode 100644 index 000000000..f49651b70 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_disabled.png new file mode 100644 index 000000000..aa622523c Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_disabled@2x.png new file mode 100644 index 000000000..ac318f5b1 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_focus.png new file mode 100644 index 000000000..0a98eab66 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_focus@2x.png new file mode 100644 index 000000000..39fd0d0e2 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_pressed.png new file mode 100644 index 000000000..049f4bfe5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_pressed@2x.png new file mode 100644 index 000000000..f58ae2238 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_closed_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end.png new file mode 100644 index 000000000..210984565 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end@2x.png new file mode 100644 index 000000000..91f3bd02d Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_disabled.png new file mode 100644 index 000000000..fe819bc14 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_disabled@2x.png new file mode 100644 index 000000000..580247709 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_focus.png new file mode 100644 index 000000000..9a978c0cc Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_focus@2x.png new file mode 100644 index 000000000..ece9b825d Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_pressed.png new file mode 100644 index 000000000..1d4050997 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_end_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_pressed@2x.png new file mode 100644 index 000000000..4822745c4 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_end_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line.png new file mode 100644 index 000000000..75cc027f8 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line@2x.png new file mode 100644 index 000000000..727370558 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_disabled.png new file mode 100644 index 000000000..01c6cffa7 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_disabled@2x.png new file mode 100644 index 000000000..57789e942 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_focus.png new file mode 100644 index 000000000..599626230 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_focus@2x.png new file mode 100644 index 000000000..34e7d603f Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_pressed.png new file mode 100644 index 000000000..6a54b0948 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_line_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_pressed@2x.png new file mode 100644 index 000000000..fb74fd324 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_line_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more.png new file mode 100644 index 000000000..045f963fa Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more@2x.png new file mode 100644 index 000000000..ccde09316 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_disabled.png new file mode 100644 index 000000000..8630b91c9 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_disabled@2x.png new file mode 100644 index 000000000..37d2cdbbd Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_focus.png new file mode 100644 index 000000000..38067367f Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_focus@2x.png new file mode 100644 index 000000000..d80ccb8cc Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_pressed.png new file mode 100644 index 000000000..a306eb288 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_more_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_pressed@2x.png new file mode 100644 index 000000000..7044b2822 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_more_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open.png new file mode 100644 index 000000000..445ec7181 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open@2x.png new file mode 100644 index 000000000..febb31878 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_disabled.png new file mode 100644 index 000000000..3b840d767 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_disabled@2x.png new file mode 100644 index 000000000..d6c5b40ed Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_focus.png new file mode 100644 index 000000000..fecf8733e Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_focus@2x.png new file mode 100644 index 000000000..296d17553 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_pressed.png new file mode 100644 index 000000000..8a7cffab5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/branch_open_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_pressed@2x.png new file mode 100644 index 000000000..24e282c85 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/branch_open_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked.png new file mode 100644 index 000000000..aa5f56720 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked@2x.png new file mode 100644 index 000000000..60b4fb2ae Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_disabled.png new file mode 100644 index 000000000..208f3709e Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png new file mode 100644 index 000000000..7c8ad0c58 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_focus.png new file mode 100644 index 000000000..a35def37f Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png new file mode 100644 index 000000000..925cd3620 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_pressed.png new file mode 100644 index 000000000..f95dc13eb Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png new file mode 100644 index 000000000..641c047ae Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate.png new file mode 100644 index 000000000..02de1ad2c Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png new file mode 100644 index 000000000..8fabf6ea4 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png new file mode 100644 index 000000000..df99affe0 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png new file mode 100644 index 000000000..3102eaa3f Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png new file mode 100644 index 000000000..370454348 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png new file mode 100644 index 000000000..8da0a8c98 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png new file mode 100644 index 000000000..b971d7fae Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png new file mode 100644 index 000000000..9e37b8433 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked.png new file mode 100644 index 000000000..80bcf2b66 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked@2x.png new file mode 100644 index 000000000..df0fa4d5a Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png new file mode 100644 index 000000000..ede58c818 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png new file mode 100644 index 000000000..6721b38f5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_focus.png new file mode 100644 index 000000000..3883d2d5a Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png new file mode 100644 index 000000000..35c061c0d Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png new file mode 100644 index 000000000..d98639eed Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png new file mode 100644 index 000000000..88a52460d Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal.png new file mode 100644 index 000000000..bc858c8d0 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal@2x.png new file mode 100644 index 000000000..7ea4f9c1c Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_disabled.png new file mode 100644 index 000000000..72e073a78 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png new file mode 100644 index 000000000..09a439df9 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_focus.png new file mode 100644 index 000000000..c84512bb5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_focus@2x.png new file mode 100644 index 000000000..8dd58f609 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_pressed.png new file mode 100644 index 000000000..7ca2605bd Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png new file mode 100644 index 000000000..bd9661781 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical.png new file mode 100644 index 000000000..49a910526 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical@2x.png new file mode 100644 index 000000000..cbb017ee6 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_disabled.png new file mode 100644 index 000000000..965854688 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_disabled@2x.png new file mode 100644 index 000000000..7836a9465 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_focus.png new file mode 100644 index 000000000..512ee7d23 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_focus@2x.png new file mode 100644 index 000000000..af503251d Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_pressed.png new file mode 100644 index 000000000..b8dd21535 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_pressed@2x.png new file mode 100644 index 000000000..e1d43a83e Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/line_vertical_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked.png new file mode 100644 index 000000000..2a1d26a4f Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked@2x.png new file mode 100644 index 000000000..eb2cbb46c Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_disabled.png new file mode 100644 index 000000000..f78c15360 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_disabled@2x.png new file mode 100644 index 000000000..30168e86b Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_focus.png new file mode 100644 index 000000000..6d9c9801c Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_focus@2x.png new file mode 100644 index 000000000..63476a075 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_pressed.png new file mode 100644 index 000000000..421ecb44a Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_pressed@2x.png new file mode 100644 index 000000000..9030e1013 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_checked_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked.png new file mode 100644 index 000000000..23b06ced3 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked@2x.png new file mode 100644 index 000000000..41e790ac7 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_disabled.png new file mode 100644 index 000000000..075ca8557 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png new file mode 100644 index 000000000..61cd48ffe Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_focus.png new file mode 100644 index 000000000..d58758039 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png new file mode 100644 index 000000000..0f12c860b Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_pressed.png new file mode 100644 index 000000000..37c09a6d8 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png new file mode 100644 index 000000000..9e424e4b3 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal.png new file mode 100644 index 000000000..9d2f51f06 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png new file mode 100644 index 000000000..c35b46532 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png new file mode 100644 index 000000000..013ac4578 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png new file mode 100644 index 000000000..f713dd4d0 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png new file mode 100644 index 000000000..6d0d42588 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png new file mode 100644 index 000000000..0a5ca39b1 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png new file mode 100644 index 000000000..e414c0c52 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png new file mode 100644 index 000000000..e8e8af20f Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical.png new file mode 100644 index 000000000..140846d75 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png new file mode 100644 index 000000000..7edf454a3 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png new file mode 100644 index 000000000..5cd85dd72 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png new file mode 100644 index 000000000..07d5ae1bf Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png new file mode 100644 index 000000000..9aac0365a Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png new file mode 100644 index 000000000..c3b1d1805 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png new file mode 100644 index 000000000..30b3921e2 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png new file mode 100644 index 000000000..bd0120745 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal.png new file mode 100644 index 000000000..96e2689ff Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png new file mode 100644 index 000000000..5944e44c9 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png new file mode 100644 index 000000000..941e14509 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png new file mode 100644 index 000000000..e44a33be6 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png new file mode 100644 index 000000000..590b31471 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png new file mode 100644 index 000000000..ca88313f6 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png new file mode 100644 index 000000000..38004682a Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png new file mode 100644 index 000000000..d4b88c047 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical.png new file mode 100644 index 000000000..b503c8093 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png new file mode 100644 index 000000000..2725a7fa1 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png new file mode 100644 index 000000000..6aa1fbdd7 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png new file mode 100644 index 000000000..8e54cfa8e Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png new file mode 100644 index 000000000..fcdfc0f21 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png new file mode 100644 index 000000000..51b083965 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png new file mode 100644 index 000000000..9d6f84d51 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png new file mode 100644 index 000000000..3876a8e87 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent_disabled.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent_disabled@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent_focus.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent_focus@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent_pressed.png new file mode 100644 index 000000000..3a95111e5 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/transparent_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/transparent_pressed@2x.png new file mode 100644 index 000000000..4c4b95225 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/transparent_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close.png new file mode 100644 index 000000000..0115ca3f3 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close@2x.png new file mode 100644 index 000000000..41dcd8160 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close_disabled.png new file mode 100644 index 000000000..55144fff8 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close_disabled@2x.png new file mode 100644 index 000000000..766aef7c1 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close_focus.png new file mode 100644 index 000000000..61df25f82 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close_focus@2x.png new file mode 100644 index 000000000..2ea50b1a9 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close_pressed.png new file mode 100644 index 000000000..042311def Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_close_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_close_pressed@2x.png new file mode 100644 index 000000000..b54d9a16d Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_close_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip.png new file mode 100644 index 000000000..9ea1c438f Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip@2x.png new file mode 100644 index 000000000..b31309e8b Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_disabled.png new file mode 100644 index 000000000..b66e23b99 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_disabled@2x.png new file mode 100644 index 000000000..ee3d0ba88 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_focus.png new file mode 100644 index 000000000..400af158c Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_focus@2x.png new file mode 100644 index 000000000..83c9ec634 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_pressed.png new file mode 100644 index 000000000..f71dd8c9a Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_grip_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_pressed@2x.png new file mode 100644 index 000000000..109878a35 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_grip_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize.png new file mode 100644 index 000000000..07517b943 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize@2x.png new file mode 100644 index 000000000..434bb07cd Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_disabled.png new file mode 100644 index 000000000..a1ee4aeda Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_disabled@2x.png new file mode 100644 index 000000000..8454ad832 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_focus.png new file mode 100644 index 000000000..3b56123f1 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_focus@2x.png new file mode 100644 index 000000000..a66fb71ec Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_pressed.png new file mode 100644 index 000000000..9b70c0ade Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_pressed@2x.png new file mode 100644 index 000000000..5750a8e7e Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_minimize_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock.png new file mode 100644 index 000000000..9be9cdf77 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock@2x.png new file mode 100644 index 000000000..40345ab94 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock_disabled.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_disabled.png new file mode 100644 index 000000000..ea92aee04 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_disabled.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock_disabled@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_disabled@2x.png new file mode 100644 index 000000000..fb8d5483c Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_disabled@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock_focus.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_focus.png new file mode 100644 index 000000000..5b0338d9b Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_focus.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock_focus@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_focus@2x.png new file mode 100644 index 000000000..9fea75b09 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_focus@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock_pressed.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_pressed.png new file mode 100644 index 000000000..4bc657b21 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_pressed.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/rc/window_undock_pressed@2x.png b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_pressed@2x.png new file mode 100644 index 000000000..2ea0c2c71 Binary files /dev/null and b/src/NotepadNext/qdarkstyle/dark/rc/window_undock_pressed@2x.png differ diff --git a/src/NotepadNext/qdarkstyle/dark/style.qrc b/src/NotepadNext/qdarkstyle/dark/style.qrc new file mode 100644 index 000000000..d74dee00a --- /dev/null +++ b/src/NotepadNext/qdarkstyle/dark/style.qrc @@ -0,0 +1,217 @@ + +<RCC warning="WARNING! File created programmatically. All changes made in this file will be lost!"> + <qresource prefix="qss_icons/dark"> + <file>rc/.keep</file> + <file>rc/arrow_down.png</file> + <file>rc/arrow_down@2x.png</file> + <file>rc/arrow_down_disabled.png</file> + <file>rc/arrow_down_disabled@2x.png</file> + <file>rc/arrow_down_focus.png</file> + <file>rc/arrow_down_focus@2x.png</file> + <file>rc/arrow_down_pressed.png</file> + <file>rc/arrow_down_pressed@2x.png</file> + <file>rc/arrow_left.png</file> + <file>rc/arrow_left@2x.png</file> + <file>rc/arrow_left_disabled.png</file> + <file>rc/arrow_left_disabled@2x.png</file> + <file>rc/arrow_left_focus.png</file> + <file>rc/arrow_left_focus@2x.png</file> + <file>rc/arrow_left_pressed.png</file> + <file>rc/arrow_left_pressed@2x.png</file> + <file>rc/arrow_right.png</file> + <file>rc/arrow_right@2x.png</file> + <file>rc/arrow_right_disabled.png</file> + <file>rc/arrow_right_disabled@2x.png</file> + <file>rc/arrow_right_focus.png</file> + <file>rc/arrow_right_focus@2x.png</file> + <file>rc/arrow_right_pressed.png</file> + <file>rc/arrow_right_pressed@2x.png</file> + <file>rc/arrow_up.png</file> + <file>rc/arrow_up@2x.png</file> + <file>rc/arrow_up_disabled.png</file> + <file>rc/arrow_up_disabled@2x.png</file> + <file>rc/arrow_up_focus.png</file> + <file>rc/arrow_up_focus@2x.png</file> + <file>rc/arrow_up_pressed.png</file> + <file>rc/arrow_up_pressed@2x.png</file> + <file>rc/base_icon.png</file> + <file>rc/base_icon@2x.png</file> + <file>rc/base_icon_disabled.png</file> + <file>rc/base_icon_disabled@2x.png</file> + <file>rc/base_icon_focus.png</file> + <file>rc/base_icon_focus@2x.png</file> + <file>rc/base_icon_pressed.png</file> + <file>rc/base_icon_pressed@2x.png</file> + <file>rc/branch_closed.png</file> + <file>rc/branch_closed@2x.png</file> + <file>rc/branch_closed_disabled.png</file> + <file>rc/branch_closed_disabled@2x.png</file> + <file>rc/branch_closed_focus.png</file> + <file>rc/branch_closed_focus@2x.png</file> + <file>rc/branch_closed_pressed.png</file> + <file>rc/branch_closed_pressed@2x.png</file> + <file>rc/branch_end.png</file> + <file>rc/branch_end@2x.png</file> + <file>rc/branch_end_disabled.png</file> + <file>rc/branch_end_disabled@2x.png</file> + <file>rc/branch_end_focus.png</file> + <file>rc/branch_end_focus@2x.png</file> + <file>rc/branch_end_pressed.png</file> + <file>rc/branch_end_pressed@2x.png</file> + <file>rc/branch_line.png</file> + <file>rc/branch_line@2x.png</file> + <file>rc/branch_line_disabled.png</file> + <file>rc/branch_line_disabled@2x.png</file> + <file>rc/branch_line_focus.png</file> + <file>rc/branch_line_focus@2x.png</file> + <file>rc/branch_line_pressed.png</file> + <file>rc/branch_line_pressed@2x.png</file> + <file>rc/branch_more.png</file> + <file>rc/branch_more@2x.png</file> + <file>rc/branch_more_disabled.png</file> + <file>rc/branch_more_disabled@2x.png</file> + <file>rc/branch_more_focus.png</file> + <file>rc/branch_more_focus@2x.png</file> + <file>rc/branch_more_pressed.png</file> + <file>rc/branch_more_pressed@2x.png</file> + <file>rc/branch_open.png</file> + <file>rc/branch_open@2x.png</file> + <file>rc/branch_open_disabled.png</file> + <file>rc/branch_open_disabled@2x.png</file> + <file>rc/branch_open_focus.png</file> + <file>rc/branch_open_focus@2x.png</file> + <file>rc/branch_open_pressed.png</file> + <file>rc/branch_open_pressed@2x.png</file> + <file>rc/checkbox_checked.png</file> + <file>rc/checkbox_checked@2x.png</file> + <file>rc/checkbox_checked_disabled.png</file> + <file>rc/checkbox_checked_disabled@2x.png</file> + <file>rc/checkbox_checked_focus.png</file> + <file>rc/checkbox_checked_focus@2x.png</file> + <file>rc/checkbox_checked_pressed.png</file> + <file>rc/checkbox_checked_pressed@2x.png</file> + <file>rc/checkbox_indeterminate.png</file> + <file>rc/checkbox_indeterminate@2x.png</file> + <file>rc/checkbox_indeterminate_disabled.png</file> + <file>rc/checkbox_indeterminate_disabled@2x.png</file> + <file>rc/checkbox_indeterminate_focus.png</file> + <file>rc/checkbox_indeterminate_focus@2x.png</file> + <file>rc/checkbox_indeterminate_pressed.png</file> + <file>rc/checkbox_indeterminate_pressed@2x.png</file> + <file>rc/checkbox_unchecked.png</file> + <file>rc/checkbox_unchecked@2x.png</file> + <file>rc/checkbox_unchecked_disabled.png</file> + <file>rc/checkbox_unchecked_disabled@2x.png</file> + <file>rc/checkbox_unchecked_focus.png</file> + <file>rc/checkbox_unchecked_focus@2x.png</file> + <file>rc/checkbox_unchecked_pressed.png</file> + <file>rc/checkbox_unchecked_pressed@2x.png</file> + <file>rc/line_horizontal.png</file> + <file>rc/line_horizontal@2x.png</file> + <file>rc/line_horizontal_disabled.png</file> + <file>rc/line_horizontal_disabled@2x.png</file> + <file>rc/line_horizontal_focus.png</file> + <file>rc/line_horizontal_focus@2x.png</file> + <file>rc/line_horizontal_pressed.png</file> + <file>rc/line_horizontal_pressed@2x.png</file> + <file>rc/line_vertical.png</file> + <file>rc/line_vertical@2x.png</file> + <file>rc/line_vertical_disabled.png</file> + <file>rc/line_vertical_disabled@2x.png</file> + <file>rc/line_vertical_focus.png</file> + <file>rc/line_vertical_focus@2x.png</file> + <file>rc/line_vertical_pressed.png</file> + <file>rc/line_vertical_pressed@2x.png</file> + <file>rc/radio_checked.png</file> + <file>rc/radio_checked@2x.png</file> + <file>rc/radio_checked_disabled.png</file> + <file>rc/radio_checked_disabled@2x.png</file> + <file>rc/radio_checked_focus.png</file> + <file>rc/radio_checked_focus@2x.png</file> + <file>rc/radio_checked_pressed.png</file> + <file>rc/radio_checked_pressed@2x.png</file> + <file>rc/radio_unchecked.png</file> + <file>rc/radio_unchecked@2x.png</file> + <file>rc/radio_unchecked_disabled.png</file> + <file>rc/radio_unchecked_disabled@2x.png</file> + <file>rc/radio_unchecked_focus.png</file> + <file>rc/radio_unchecked_focus@2x.png</file> + <file>rc/radio_unchecked_pressed.png</file> + <file>rc/radio_unchecked_pressed@2x.png</file> + <file>rc/toolbar_move_horizontal.png</file> + <file>rc/toolbar_move_horizontal@2x.png</file> + <file>rc/toolbar_move_horizontal_disabled.png</file> + <file>rc/toolbar_move_horizontal_disabled@2x.png</file> + <file>rc/toolbar_move_horizontal_focus.png</file> + <file>rc/toolbar_move_horizontal_focus@2x.png</file> + <file>rc/toolbar_move_horizontal_pressed.png</file> + <file>rc/toolbar_move_horizontal_pressed@2x.png</file> + <file>rc/toolbar_move_vertical.png</file> + <file>rc/toolbar_move_vertical@2x.png</file> + <file>rc/toolbar_move_vertical_disabled.png</file> + <file>rc/toolbar_move_vertical_disabled@2x.png</file> + <file>rc/toolbar_move_vertical_focus.png</file> + <file>rc/toolbar_move_vertical_focus@2x.png</file> + <file>rc/toolbar_move_vertical_pressed.png</file> + <file>rc/toolbar_move_vertical_pressed@2x.png</file> + <file>rc/toolbar_separator_horizontal.png</file> + <file>rc/toolbar_separator_horizontal@2x.png</file> + <file>rc/toolbar_separator_horizontal_disabled.png</file> + <file>rc/toolbar_separator_horizontal_disabled@2x.png</file> + <file>rc/toolbar_separator_horizontal_focus.png</file> + <file>rc/toolbar_separator_horizontal_focus@2x.png</file> + <file>rc/toolbar_separator_horizontal_pressed.png</file> + <file>rc/toolbar_separator_horizontal_pressed@2x.png</file> + <file>rc/toolbar_separator_vertical.png</file> + <file>rc/toolbar_separator_vertical@2x.png</file> + <file>rc/toolbar_separator_vertical_disabled.png</file> + <file>rc/toolbar_separator_vertical_disabled@2x.png</file> + <file>rc/toolbar_separator_vertical_focus.png</file> + <file>rc/toolbar_separator_vertical_focus@2x.png</file> + <file>rc/toolbar_separator_vertical_pressed.png</file> + <file>rc/toolbar_separator_vertical_pressed@2x.png</file> + <file>rc/transparent.png</file> + <file>rc/transparent@2x.png</file> + <file>rc/transparent_disabled.png</file> + <file>rc/transparent_disabled@2x.png</file> + <file>rc/transparent_focus.png</file> + <file>rc/transparent_focus@2x.png</file> + <file>rc/transparent_pressed.png</file> + <file>rc/transparent_pressed@2x.png</file> + <file>rc/window_close.png</file> + <file>rc/window_close@2x.png</file> + <file>rc/window_close_disabled.png</file> + <file>rc/window_close_disabled@2x.png</file> + <file>rc/window_close_focus.png</file> + <file>rc/window_close_focus@2x.png</file> + <file>rc/window_close_pressed.png</file> + <file>rc/window_close_pressed@2x.png</file> + <file>rc/window_grip.png</file> + <file>rc/window_grip@2x.png</file> + <file>rc/window_grip_disabled.png</file> + <file>rc/window_grip_disabled@2x.png</file> + <file>rc/window_grip_focus.png</file> + <file>rc/window_grip_focus@2x.png</file> + <file>rc/window_grip_pressed.png</file> + <file>rc/window_grip_pressed@2x.png</file> + <file>rc/window_minimize.png</file> + <file>rc/window_minimize@2x.png</file> + <file>rc/window_minimize_disabled.png</file> + <file>rc/window_minimize_disabled@2x.png</file> + <file>rc/window_minimize_focus.png</file> + <file>rc/window_minimize_focus@2x.png</file> + <file>rc/window_minimize_pressed.png</file> + <file>rc/window_minimize_pressed@2x.png</file> + <file>rc/window_undock.png</file> + <file>rc/window_undock@2x.png</file> + <file>rc/window_undock_disabled.png</file> + <file>rc/window_undock_disabled@2x.png</file> + <file>rc/window_undock_focus.png</file> + <file>rc/window_undock_focus@2x.png</file> + <file>rc/window_undock_pressed.png</file> + <file>rc/window_undock_pressed@2x.png</file> + </qresource> + <qresource prefix="qdarkstyle/dark"> + <file>style.qss</file> + </qresource> +</RCC> diff --git a/src/NotepadNext/qdarkstyle/dark/style.qss b/src/NotepadNext/qdarkstyle/dark/style.qss new file mode 100644 index 000000000..b392674fd --- /dev/null +++ b/src/NotepadNext/qdarkstyle/dark/style.qss @@ -0,0 +1,2212 @@ +/* --------------------------------------------------------------------------- + + WARNING! File created programmatically. All changes made in this file will be lost! + + Created by the qtsass compiler v0.3.0 + + The definitions are in the "qdarkstyle.qss._styles.scss" module + +--------------------------------------------------------------------------- */ +/* Light Style - QDarkStyleSheet ------------------------------------------ */ +/* + +See Qt documentation: + + - https://doc.qt.io/qt-5/stylesheet.html + - https://doc.qt.io/qt-5/stylesheet-reference.html + - https://doc.qt.io/qt-5/stylesheet-examples.html + +--------------------------------------------------------------------------- */ +/* Reset elements ------------------------------------------------------------ + +Resetting everything helps to unify styles across different operating systems + +--------------------------------------------------------------------------- */ +* { + padding: 0px; + margin: 0px; + border: 0px; + border-style: none; + border-image: none; + outline: 0; +} + +/* specific reset for elements inside QToolBar */ +QToolBar * { + margin: 0px; + padding: 0px; +} + +/* QWidget ---------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QWidget { + background-color: #19232D; + border: 0px solid #455364; + padding: 0px; + color: #E0E1E3; + selection-background-color: #346792; + selection-color: #E0E1E3; +} + +QWidget:disabled { + background-color: #19232D; + color: #9DA9B5; + selection-background-color: #26486B; + selection-color: #9DA9B5; +} + +QWidget::item:selected { + background-color: #346792; +} + +QWidget::item:hover:!selected { + background-color: #1A72BB; +} + +/* QMainWindow ------------------------------------------------------------ + +This adjusts the splitter in the dock widget, not qsplitter +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow + +--------------------------------------------------------------------------- */ +QMainWindow::separator { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 2px; +} + +QMainWindow::separator:hover { + background-color: #60798B; + border: 0px solid #1A72BB; +} + +QMainWindow::separator:horizontal { + width: 5px; + margin-top: 2px; + margin-bottom: 2px; + image: url(":/qss_icons/dark/rc/toolbar_separator_vertical.png"); +} + +QMainWindow::separator:vertical { + height: 5px; + margin-left: 2px; + margin-right: 2px; + image: url(":/qss_icons/dark/rc/toolbar_separator_horizontal.png"); +} + +/* QToolTip --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip + +--------------------------------------------------------------------------- */ +QToolTip { + background-color: #346792; + color: #E0E1E3; + /* If you remove the border property, background stops working on Windows */ + border: none; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Remove opacity, fix #174 - may need to use RGBA */ +} + +/* QStatusBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar + +--------------------------------------------------------------------------- */ +QStatusBar { + border: 1px solid #455364; + /* Fixes Spyder #9120, #9121 */ + background: #455364; + /* Fixes #205, white vertical borders separating items */ +} + +QStatusBar::item { + border: none; +} + +QStatusBar QToolTip { + background-color: #1A72BB; + border: 1px solid #19232D; + color: #19232D; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Reducing transparency to read better */ + opacity: 230; +} + +QStatusBar QLabel { + /* Fixes Spyder #9120, #9121 */ + background: transparent; +} + +/* QCheckBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox + +--------------------------------------------------------------------------- */ +QCheckBox { + background-color: #19232D; + color: #E0E1E3; + spacing: 4px; + outline: none; + padding-top: 4px; + padding-bottom: 4px; +} + +QCheckBox:focus { + border: none; +} + +QCheckBox QWidget:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QCheckBox::indicator { + margin-left: 2px; + height: 14px; + width: 14px; +} + +QCheckBox::indicator:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:focus, QCheckBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QCheckBox::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QCheckBox::indicator:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QCheckBox::indicator:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +QCheckBox::indicator:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QCheckBox::indicator:indeterminate:disabled { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_disabled.png"); +} + +QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:hover, QCheckBox::indicator:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + font-weight: bold; + border: 1px solid #455364; + border-radius: 4px; + padding: 2px; + margin-top: 6px; + margin-bottom: 4px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 4px; + padding-left: 2px; + padding-right: 4px; + padding-top: -4px; +} + +QGroupBox::indicator { + margin-left: 2px; + margin-top: 2px; + padding: 0; + height: 14px; + width: 14px; +} + +QGroupBox::indicator:unchecked { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QGroupBox::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QGroupBox::indicator:checked { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QGroupBox::indicator:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +/* QRadioButton ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton + +--------------------------------------------------------------------------- */ +QRadioButton { + background-color: #19232D; + color: #E0E1E3; + spacing: 4px; + padding-top: 4px; + padding-bottom: 4px; + border: none; + outline: none; +} + +QRadioButton:focus { + border: none; +} + +QRadioButton:disabled { + background-color: #19232D; + color: #9DA9B5; + border: none; + outline: none; +} + +QRadioButton QWidget { + background-color: #19232D; + color: #E0E1E3; + spacing: 0px; + padding: 0px; + outline: none; + border: none; +} + +QRadioButton::indicator { + border: none; + outline: none; + margin-left: 2px; + height: 14px; + width: 14px; +} + +QRadioButton::indicator:unchecked { + image: url(":/qss_icons/dark/rc/radio_unchecked.png"); +} + +QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:focus, QRadioButton::indicator:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_unchecked_focus.png"); +} + +QRadioButton::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/radio_unchecked_disabled.png"); +} + +QRadioButton::indicator:checked { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked.png"); +} + +QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:focus, QRadioButton::indicator:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_focus.png"); +} + +QRadioButton::indicator:checked:disabled { + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_disabled.png"); +} + +/* QMenuBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar + +--------------------------------------------------------------------------- */ +QMenuBar { + background-color: #455364; + padding: 2px; + border: 1px solid #19232D; + color: #E0E1E3; + selection-background-color: #1A72BB; +} + +QMenuBar:focus { + border: 1px solid #346792; +} + +QMenuBar::item { + background: transparent; + padding: 4px; +} + +QMenuBar::item:selected { + padding: 4px; + background: transparent; + border: 0px solid #455364; + background-color: #1A72BB; +} + +QMenuBar::item:pressed { + padding: 4px; + border: 0px solid #455364; + background-color: #1A72BB; + color: #E0E1E3; + margin-bottom: 0px; + padding-bottom: 0px; +} + +/* QMenu ------------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + border: 0px solid #455364; + color: #E0E1E3; + margin: 0px; + background-color: #37414F; + selection-background-color: #1A72BB; +} + +QMenu::separator { + height: 1px; + background-color: #60798B; + color: #E0E1E3; +} + +QMenu::item { + background-color: #37414F; + padding: 4px 24px 4px 28px; + /* Reserve space for selection border */ + border: 1px transparent #455364; +} + +QMenu::item:selected { + color: #E0E1E3; + background-color: #1A72BB; +} + +QMenu::item:pressed { + background-color: #1A72BB; +} + +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +QMenu::indicator { + padding-left: 8px; + width: 12px; + height: 12px; + /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ + /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ +} + +QMenu::indicator:non-exclusive:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QMenu::indicator:non-exclusive:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QMenu::indicator:non-exclusive:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QMenu::indicator:non-exclusive:checked:hover, QMenu::indicator:non-exclusive:checked:focus, QMenu::indicator:non-exclusive:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QMenu::indicator:non-exclusive:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:disabled { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:focus, QMenu::indicator:non-exclusive:indeterminate:hover, QMenu::indicator:non-exclusive:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +QMenu::indicator:exclusive:unchecked { + image: url(":/qss_icons/dark/rc/radio_unchecked.png"); +} + +QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked:focus, QMenu::indicator:exclusive:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_unchecked_focus.png"); +} + +QMenu::indicator:exclusive:unchecked:disabled { + image: url(":/qss_icons/dark/rc/radio_unchecked_disabled.png"); +} + +QMenu::indicator:exclusive:checked { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked.png"); +} + +QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_focus.png"); +} + +QMenu::indicator:exclusive:checked:disabled { + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_disabled.png"); +} + +QMenu::right-arrow { + margin: 5px; + padding-left: 12px; + image: url(":/qss_icons/dark/rc/arrow_right.png"); + height: 12px; + width: 12px; +} + +/* QAbstractItemView ------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QAbstractItemView { + alternate-background-color: #19232D; + color: #E0E1E3; + border: 1px solid #455364; + border-radius: 4px; +} + +QAbstractItemView QLineEdit { + padding: 2px; +} + +/* QAbstractScrollArea ---------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QAbstractScrollArea { + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + /* fix #159 */ + padding: 2px; + /* remove min-height to fix #244 */ + color: #E0E1E3; +} + +QAbstractScrollArea:disabled { + color: #9DA9B5; +} + +/* QScrollArea ------------------------------------------------------------ + +--------------------------------------------------------------------------- */ +QScrollArea QWidget QWidget:disabled { + background-color: #19232D; +} + +/* QScrollBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar + +--------------------------------------------------------------------------- */ +QScrollBar:horizontal { + height: 16px; + margin: 2px 16px 2px 16px; + border: 1px solid #455364; + border-radius: 4px; + background-color: #19232D; +} + +QScrollBar:vertical { + background-color: #19232D; + width: 16px; + margin: 16px 2px 16px 2px; + border: 1px solid #455364; + border-radius: 4px; +} + +QScrollBar::handle:horizontal { + background-color: #60798B; + border: 1px solid #455364; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::handle:vertical { + background-color: #60798B; + border: 1px solid #455364; + min-height: 8px; + border-radius: 4px; +} + +QScrollBar::handle:vertical:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-height: 8px; +} + +QScrollBar::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::add-line:horizontal { + margin: 0px 0px 0px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_right_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { + border-image: url(":/qss_icons/dark/rc/arrow_right.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { + border-image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal { + margin: 0px 3px 0px 3px; + border-image: url(":/qss_icons/dark/rc/arrow_left_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { + border-image: url(":/qss_icons/dark/rc/arrow_left.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_up_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { + border-image: url(":/qss_icons/dark/rc/arrow_up.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal { + background: none; +} + +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; +} + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; +} + +/* QTextEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets + +--------------------------------------------------------------------------- */ +QTextEdit { + background-color: #19232D; + color: #E0E1E3; + border-radius: 4px; + border: 1px solid #455364; +} + +QTextEdit:focus { + border: 1px solid #1A72BB; +} + +QTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QPlainTextEdit --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QPlainTextEdit { + background-color: #19232D; + color: #E0E1E3; + border-radius: 4px; + border: 1px solid #455364; +} + +QPlainTextEdit:focus { + border: 1px solid #1A72BB; +} + +QPlainTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QSizeGrip -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip + +--------------------------------------------------------------------------- */ +QSizeGrip { + background: transparent; + width: 12px; + height: 12px; + image: url(":/qss_icons/dark/rc/window_grip.png"); +} + +/* QStackedWidget --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QStackedWidget { + padding: 2px; + border: 1px solid #455364; + border: 1px solid #19232D; +} + +/* QToolBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar + +--------------------------------------------------------------------------- */ +QToolBar { + background-color: #455364; + border-bottom: 1px solid #19232D; + padding: 1px; + font-weight: bold; + spacing: 2px; +} + +QToolBar:disabled { + /* Fixes #272 */ + background-color: #455364; +} + +QToolBar::handle:horizontal { + width: 16px; + image: url(":/qss_icons/dark/rc/toolbar_move_horizontal.png"); +} + +QToolBar::handle:vertical { + height: 16px; + image: url(":/qss_icons/dark/rc/toolbar_move_vertical.png"); +} + +QToolBar::separator:horizontal { + width: 16px; + image: url(":/qss_icons/dark/rc/toolbar_separator_horizontal.png"); +} + +QToolBar::separator:vertical { + height: 16px; + image: url(":/qss_icons/dark/rc/toolbar_separator_vertical.png"); +} + +QToolButton#qt_toolbar_ext_button { + background: #455364; + border: 0px; + color: #E0E1E3; + image: url(":/qss_icons/dark/rc/arrow_right.png"); +} + +/* QAbstractSpinBox ------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractSpinBox { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + border-radius: 4px; + /* min-width: 5px; removed to fix 109 */ +} + +QAbstractSpinBox:up-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: top right; + border-left: 1px solid #455364; + border-bottom: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-bottom: -1px; +} + +QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { + image: url(":/qss_icons/dark/rc/arrow_up_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::up-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_up.png"); +} + +QAbstractSpinBox:down-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: bottom right; + border-left: 1px solid #455364; + border-top: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-top: -1px; +} + +QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::down-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QAbstractSpinBox:hover { + border: 1px solid #346792; + color: #E0E1E3; +} + +QAbstractSpinBox:focus { + border: 1px solid #1A72BB; +} + +QAbstractSpinBox:selected { + background: #346792; + color: #455364; +} + +/* ------------------------------------------------------------------------ */ +/* DISPLAYS --------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QLabel ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe + +--------------------------------------------------------------------------- */ +QLabel { + background-color: #19232D; + border: 0px solid #455364; + padding: 2px; + margin: 0px; + color: #E0E1E3; +} + +QLabel:disabled { + background-color: #19232D; + border: 0px solid #455364; + color: #9DA9B5; +} + +/* QTextBrowser ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QTextBrowser { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; +} + +QTextBrowser:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #9DA9B5; + border-radius: 4px; +} + +QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed { + border: 1px solid #455364; +} + +/* QGraphicsView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QGraphicsView { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; +} + +QGraphicsView:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #9DA9B5; + border-radius: 4px; +} + +QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed { + border: 1px solid #455364; +} + +/* QCalendarWidget -------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCalendarWidget { + border: 1px solid #455364; + border-radius: 4px; +} + +QCalendarWidget:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +/* QLCDNumber ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QLCDNumber { + background-color: #19232D; + color: #E0E1E3; +} + +QLCDNumber:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +/* QProgressBar ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar + +--------------------------------------------------------------------------- */ +QProgressBar { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; + text-align: center; +} + +QProgressBar:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #9DA9B5; + border-radius: 4px; + text-align: center; +} + +QProgressBar::chunk { + background-color: #346792; + color: #19232D; + border-radius: 4px; +} + +QProgressBar::chunk:disabled { + background-color: #26486B; + color: #9DA9B5; + border-radius: 4px; +} + +/* ------------------------------------------------------------------------ */ +/* BUTTONS ---------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QPushButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton + +--------------------------------------------------------------------------- */ +QPushButton { + background-color: #455364; + color: #E0E1E3; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; +} + +QPushButton:disabled { + background-color: #455364; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; +} + +QPushButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:disabled { + background-color: #60798B; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:selected { + background: #60798B; +} + +QPushButton:hover { + background-color: #54687A; + color: #E0E1E3; +} + +QPushButton:pressed { + background-color: #60798B; +} + +QPushButton:selected { + background: #60798B; + color: #E0E1E3; +} + +QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + bottom: 4px; +} + +QDialogButtonBox QPushButton { + /* Issue #194 #248 - Special case of QPushButton inside dialogs, for better UI */ + min-width: 80px; +} + +/* QToolButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton + +--------------------------------------------------------------------------- */ +QToolButton { + background-color: #455364; + color: #E0E1E3; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; + /* The subcontrols below are used only in the DelayedPopup mode */ + /* The subcontrols below are used only in the MenuButtonPopup mode */ + /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ +} + +QToolButton:disabled { + background-color: #455364; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; +} + +QToolButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:disabled { + background-color: #60798B; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:hover { + background-color: #54687A; + color: #E0E1E3; +} + +QToolButton:checked:pressed { + background-color: #60798B; +} + +QToolButton:checked:selected { + background: #60798B; + color: #E0E1E3; +} + +QToolButton:hover { + background-color: #54687A; + color: #E0E1E3; +} + +QToolButton:pressed { + background-color: #60798B; +} + +QToolButton:selected { + background: #60798B; + color: #E0E1E3; +} + +QToolButton[popupMode="0"] { + /* Only for DelayedPopup */ + padding-right: 2px; +} + +QToolButton[popupMode="1"] { + /* Only for MenuButtonPopup */ + padding-right: 20px; +} + +QToolButton[popupMode="1"]::menu-button { + border: none; +} + +QToolButton[popupMode="1"]::menu-button:hover { + border: none; + border-left: 1px solid #455364; + border-radius: 0; +} + +QToolButton[popupMode="2"] { + /* Only for InstantPopup */ + padding-right: 2px; +} + +QToolButton::menu-button { + padding: 2px; + border-radius: 4px; + width: 12px; + border: none; + outline: none; +} + +QToolButton::menu-button:hover { + border: 1px solid #346792; +} + +QToolButton::menu-button:checked:hover { + border: 1px solid #346792; +} + +QToolButton::menu-indicator { + image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 8px; + width: 8px; + top: 0; + /* Exclude a shift for better image */ + left: -2px; + /* Shift it a bit */ +} + +QToolButton::menu-arrow { + image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 8px; + width: 8px; +} + +QToolButton::menu-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_down_focus.png"); +} + +/* QCommandLinkButton ----------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCommandLinkButton { + background-color: transparent; + border: 1px solid #455364; + color: #E0E1E3; + border-radius: 4px; + padding: 0px; + margin: 0px; +} + +QCommandLinkButton:disabled { + background-color: transparent; + color: #9DA9B5; +} + +/* ------------------------------------------------------------------------ */ +/* INPUTS - NO FIELDS ----------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QComboBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QComboBox { + border: 1px solid #455364; + border-radius: 4px; + selection-background-color: #346792; + padding-left: 4px; + padding-right: 4px; + /* padding-right = 36; 4 + 16*2 See scrollbar size */ + /* changed to 4px to fix #239 */ + /* Fixes #103, #111 */ + min-height: 1.5em; + /* padding-top: 2px; removed to fix #132 */ + /* padding-bottom: 2px; removed to fix #132 */ + /* min-width: 75px; removed to fix #109 */ + /* Needed to remove indicator - fix #132 */ +} + +QComboBox QAbstractItemView { + border: 1px solid #455364; + border-radius: 0; + background-color: #19232D; + selection-background-color: #346792; +} + +QComboBox QAbstractItemView:hover { + background-color: #19232D; + color: #E0E1E3; +} + +QComboBox QAbstractItemView:selected { + background: #346792; + color: #455364; +} + +QComboBox QAbstractItemView:alternate { + background: #19232D; +} + +QComboBox:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QComboBox:hover { + border: 1px solid #346792; +} + +QComboBox:focus { + border: 1px solid #1A72BB; +} + +QComboBox:on { + selection-background-color: #346792; +} + +QComboBox::indicator { + border: none; + border-radius: 0; + background-color: transparent; + selection-background-color: transparent; + color: transparent; + selection-color: transparent; + /* Needed to remove indicator - fix #132 */ +} + +QComboBox::indicator:alternate { + background: #19232D; +} + +QComboBox::item:alternate { + background: #19232D; +} + +QComboBox::item:checked { + font-weight: bold; +} + +QComboBox::item:selected { + border: 0px solid transparent; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QComboBox::down-arrow { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +/* QSlider ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider + +--------------------------------------------------------------------------- */ +QSlider:disabled { + background: #19232D; +} + +QSlider:focus { + border: none; +} + +QSlider::groove:horizontal { + background: #455364; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::groove:vertical { + background: #455364; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical { + background: #346792; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical :disabled { + background: #26486B; +} + +QSlider::sub-page:horizontal { + background: #346792; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::sub-page:horizontal:disabled { + background: #26486B; +} + +QSlider::handle:horizontal { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: -8px 0px; + border-radius: 4px; +} + +QSlider::handle:horizontal:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QSlider::handle:vertical { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: 0 -8px; + border-radius: 4px; +} + +QSlider::handle:vertical:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +/* QLineEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit + +--------------------------------------------------------------------------- */ +QLineEdit { + background-color: #19232D; + padding-top: 2px; + /* This QLineEdit fix 103, 111 */ + padding-bottom: 2px; + /* This QLineEdit fix 103, 111 */ + padding-left: 4px; + padding-right: 4px; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + color: #E0E1E3; +} + +QLineEdit:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QLineEdit:hover { + border: 1px solid #346792; + color: #E0E1E3; +} + +QLineEdit:focus { + border: 1px solid #1A72BB; +} + +QLineEdit:selected { + background-color: #346792; + color: #455364; +} + +/* QTabWiget -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabWidget { + padding: 2px; + selection-background-color: #455364; +} + +QTabWidget QWidget { + /* Fixes #189 */ + border-radius: 4px; +} + +QTabWidget::pane { + border: 1px solid #455364; + border-radius: 4px; + margin: 0px; + /* Fixes double border inside pane with pyqt5 */ + padding: 0px; +} + +QTabWidget::pane:selected { + background-color: #455364; + border: 1px solid #346792; +} + +/* QTabBar ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabBar, QDockWidget QTabBar { + qproperty-drawBase: 0; + border-radius: 4px; + margin: 0px; + padding: 2px; + border: 0; + /* left: 5px; move to the right by 5px - removed for fix */ +} + +QTabBar::close-button, QDockWidget QTabBar::close-button { + border: 0; + margin: 0; + padding: 4px; + image: url(":/qss_icons/dark/rc/window_close.png"); +} + +QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { + image: url(":/qss_icons/dark/rc/window_close_focus.png"); +} + +QTabBar::close-button:pressed, QDockWidget QTabBar::close-button:pressed { + image: url(":/qss_icons/dark/rc/window_close_pressed.png"); +} + +QTabBar::tab, QDockWidget QTabBar::tab { + /* !selected and disabled ----------------------------------------- */ + /* selected ------------------------------------------------------- */ +} + +QTabBar::tab:top:selected:disabled, QDockWidget QTabBar::tab:top:selected:disabled { + border-bottom: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:bottom:selected:disabled, QDockWidget QTabBar::tab:bottom:selected:disabled { + border-top: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:left:selected:disabled, QDockWidget QTabBar::tab:left:selected:disabled { + border-right: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:disabled { + border-left: 3px solid #26486B; + color: #9DA9B5; + background-color: #455364; +} + +QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { + border-bottom: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { + border-top: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { + border-right: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { + border-left: 3px solid #19232D; + color: #9DA9B5; + background-color: #19232D; +} + +QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { + border-bottom: 2px solid #19232D; + margin-top: 2px; +} + +QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { + border-top: 2px solid #19232D; + margin-bottom: 2px; +} + +QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { + border-left: 2px solid #19232D; + margin-right: 2px; +} + +QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { + border-right: 2px solid #19232D; + margin-left: 2px; +} + +QTabBar::tab:top, QDockWidget QTabBar::tab:top { + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + min-width: 5px; + border-bottom: 3px solid #455364; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { + background-color: #54687A; + border-bottom: 3px solid #259AE9; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { + border: 1px solid #1A72BB; + border-bottom: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { + border-top: 3px solid #455364; + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + min-width: 5px; +} + +QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { + background-color: #54687A; + border-top: 3px solid #259AE9; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { + border: 1px solid #1A72BB; + border-top: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:left, QDockWidget QTabBar::tab:left { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { + background-color: #54687A; + border-right: 3px solid #259AE9; +} + +QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { + border: 1px solid #1A72BB; + border-right: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-right: 0px; + padding-right: -1px; +} + +QTabBar::tab:right, QDockWidget QTabBar::tab:right { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { + background-color: #54687A; + border-left: 3px solid #259AE9; +} + +QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { + border: 1px solid #1A72BB; + border-left: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-left: 0px; + padding-left: 0px; +} + +QTabBar QToolButton, QDockWidget QTabBar QToolButton { + /* Fixes #136 */ + background-color: #455364; + height: 12px; + width: 12px; +} + +QTabBar QToolButton:pressed, QDockWidget QTabBar QToolButton:pressed { + background-color: #455364; +} + +QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover { + border: 1px solid #346792; +} + +QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { + image: url(":/qss_icons/dark/rc/arrow_left.png"); +} + +QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { + image: url(":/qss_icons/dark/rc/arrow_left_disabled.png"); +} + +QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { + image: url(":/qss_icons/dark/rc/arrow_right.png"); +} + +QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { + image: url(":/qss_icons/dark/rc/arrow_right_disabled.png"); +} + +/* QDockWiget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QDockWidget { + outline: 1px solid #455364; + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + titlebar-close-icon: url(":/qss_icons/dark/rc/transparent.png"); + titlebar-normal-icon: url(":/qss_icons/dark/rc/transparent.png"); +} + +QDockWidget::title { + /* Better size for title bar */ + padding: 3px; + spacing: 4px; + border: none; + background-color: #455364; +} + +QDockWidget::close-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/dark/rc/window_close.png"); +} + +QDockWidget::close-button:hover { + image: url(":/qss_icons/dark/rc/window_close_focus.png"); +} + +QDockWidget::close-button:pressed { + image: url(":/qss_icons/dark/rc/window_close_pressed.png"); +} + +QDockWidget::float-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/dark/rc/window_undock.png"); +} + +QDockWidget::float-button:hover { + image: url(":/qss_icons/dark/rc/window_undock_focus.png"); +} + +QDockWidget::float-button:pressed { + image: url(":/qss_icons/dark/rc/window_undock_pressed.png"); +} + +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView:branch:selected, QTreeView:branch:hover { + background: url(":/qss_icons/dark/rc/transparent.png"); +} + +QTreeView:branch:has-siblings:!adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_line.png") 0; +} + +QTreeView:branch:has-siblings:adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_more.png") 0; +} + +QTreeView:branch:!has-children:!has-siblings:adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_end.png") 0; +} + +QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/dark/rc/branch_closed.png"); +} + +QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/dark/rc/branch_open.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover { + image: url(":/qss_icons/dark/rc/branch_closed_focus.png"); +} + +QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover { + image: url(":/qss_icons/dark/rc/branch_open_focus.png"); +} + +QTreeView::indicator:checked, +QListView::indicator:checked, +QTableView::indicator:checked, +QColumnView::indicator:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QTreeView::indicator:checked:hover, QTreeView::indicator:checked:focus, QTreeView::indicator:checked:pressed, +QListView::indicator:checked:hover, +QListView::indicator:checked:focus, +QListView::indicator:checked:pressed, +QTableView::indicator:checked:hover, +QTableView::indicator:checked:focus, +QTableView::indicator:checked:pressed, +QColumnView::indicator:checked:hover, +QColumnView::indicator:checked:focus, +QColumnView::indicator:checked:pressed { + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QTreeView::indicator:unchecked, +QListView::indicator:unchecked, +QTableView::indicator:unchecked, +QColumnView::indicator:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, +QListView::indicator:unchecked:hover, +QListView::indicator:unchecked:focus, +QListView::indicator:unchecked:pressed, +QTableView::indicator:unchecked:hover, +QTableView::indicator:unchecked:focus, +QTableView::indicator:unchecked:pressed, +QColumnView::indicator:unchecked:hover, +QColumnView::indicator:unchecked:focus, +QColumnView::indicator:unchecked:pressed { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QTreeView::indicator:indeterminate, +QListView::indicator:indeterminate, +QTableView::indicator:indeterminate, +QColumnView::indicator:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed, +QListView::indicator:indeterminate:hover, +QListView::indicator:indeterminate:focus, +QListView::indicator:indeterminate:pressed, +QTableView::indicator:indeterminate:hover, +QTableView::indicator:indeterminate:focus, +QTableView::indicator:indeterminate:pressed, +QColumnView::indicator:indeterminate:hover, +QColumnView::indicator:indeterminate:focus, +QColumnView::indicator:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + gridline-color: #455364; + border-radius: 4px; +} + +QTreeView:disabled, +QListView:disabled, +QTableView:disabled, +QColumnView:disabled { + background-color: #19232D; + color: #9DA9B5; +} + +QTreeView:selected, +QListView:selected, +QTableView:selected, +QColumnView:selected { + background-color: #346792; + color: #455364; +} + +QTreeView:focus, +QListView:focus, +QTableView:focus, +QColumnView:focus { + border: 1px solid #1A72BB; +} + +QTreeView::item:pressed, +QListView::item:pressed, +QTableView::item:pressed, +QColumnView::item:pressed { + background-color: #346792; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, +QTableView::item:selected:active, +QColumnView::item:selected:active { + background-color: #346792; +} + +QTreeView::item:selected:!active, +QListView::item:selected:!active, +QTableView::item:selected:!active, +QColumnView::item:selected:!active { + color: #E0E1E3; + background-color: #37414F; +} + +QTreeView::item:!selected:hover, +QListView::item:!selected:hover, +QTableView::item:!selected:hover, +QColumnView::item:!selected:hover { + outline: 0; + color: #E0E1E3; + background-color: #37414F; +} + +QTableCornerButton::section { + background-color: #19232D; + border: 1px transparent #455364; + border-radius: 0px; +} + +/* QHeaderView ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview + +--------------------------------------------------------------------------- */ +QHeaderView { + background-color: #455364; + border: 0px transparent #455364; + padding: 0; + margin: 0; + border-radius: 0; +} + +QHeaderView:disabled { + background-color: #455364; + border: 1px transparent #455364; +} + +QHeaderView::section { + background-color: #455364; + color: #E0E1E3; + border-radius: 0; + text-align: left; + font-size: 13px; +} + +QHeaderView::section::horizontal { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-left: 1px solid #19232D; +} + +QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { + border-left: 1px solid #455364; +} + +QHeaderView::section::horizontal:disabled { + color: #9DA9B5; +} + +QHeaderView::section::vertical { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-top: 1px solid #19232D; +} + +QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { + border-top: 1px solid #455364; +} + +QHeaderView::section::vertical:disabled { + color: #9DA9B5; +} + +QHeaderView::down-arrow { + /* Those settings (border/width/height/background-color) solve bug */ + /* transparent arrow background and size */ + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QHeaderView::up-arrow { + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/dark/rc/arrow_up.png"); +} + +/* QToolBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox + +--------------------------------------------------------------------------- */ +QToolBox { + padding: 0px; + border: 0px; + border: 1px solid #455364; +} + +QToolBox:selected { + padding: 0px; + border: 2px solid #346792; +} + +QToolBox::tab { + background-color: #19232D; + border: 1px solid #455364; + color: #E0E1E3; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QToolBox::tab:disabled { + color: #9DA9B5; +} + +QToolBox::tab:selected { + background-color: #60798B; + border-bottom: 2px solid #346792; +} + +QToolBox::tab:selected:disabled { + background-color: #455364; + border-bottom: 2px solid #26486B; +} + +QToolBox::tab:!selected { + background-color: #455364; + border-bottom: 2px solid #455364; +} + +QToolBox::tab:!selected:disabled { + background-color: #19232D; +} + +QToolBox::tab:hover { + border-color: #1A72BB; + border-bottom: 2px solid #1A72BB; +} + +QToolBox QScrollArea QWidget QWidget { + padding: 0px; + border: 0px; + background-color: #19232D; +} + +/* QFrame ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe +https://doc.qt.io/qt-5/qframe.html#-prop +https://doc.qt.io/qt-5/qframe.html#details +https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color + +--------------------------------------------------------------------------- */ +/* (dot) .QFrame fix #141, #126, #123 */ +.QFrame { + border-radius: 4px; + border: 1px solid #455364; + /* No frame */ + /* HLine */ + /* HLine */ +} + +.QFrame[frameShape="0"] { + border-radius: 4px; + border: 1px transparent #455364; +} + +.QFrame[frameShape="4"] { + max-height: 2px; + border: none; + background-color: #455364; +} + +.QFrame[frameShape="5"] { + max-width: 2px; + border: none; + background-color: #455364; +} + +/* QSplitter -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter + +--------------------------------------------------------------------------- */ +QSplitter { + background-color: #455364; + spacing: 0px; + padding: 0px; + margin: 0px; +} + +QSplitter::handle { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 1px; + margin: 0px; +} + +QSplitter::handle:hover { + background-color: #9DA9B5; +} + +QSplitter::handle:horizontal { + width: 5px; + image: url(":/qss_icons/dark/rc/line_vertical.png"); +} + +QSplitter::handle:vertical { + height: 5px; + image: url(":/qss_icons/dark/rc/line_horizontal.png"); +} + +/* QDateEdit, QDateTimeEdit ----------------------------------------------- + +--------------------------------------------------------------------------- */ +QDateEdit, QDateTimeEdit { + selection-background-color: #346792; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + min-width: 10px; +} + +QDateEdit:on, QDateTimeEdit:on { + selection-background-color: #346792; +} + +QDateEdit::drop-down, QDateTimeEdit::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QDateEdit::down-arrow, QDateTimeEdit::down-arrow { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { + background-color: #19232D; + border-radius: 4px; + border: 1px solid #455364; + selection-background-color: #346792; +} + +/* QAbstractView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractView:hover { + border: 1px solid #346792; + color: #E0E1E3; +} + +QAbstractView:selected { + background: #346792; + color: #455364; +} + +/* PlotWidget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +PlotWidget { + /* Fix cut labels in plots #134 */ + padding: 0px; +} diff --git a/src/NotepadNext/resources.qrc b/src/NotepadNext/resources.qrc new file mode 100644 index 000000000..7043376d3 --- /dev/null +++ b/src/NotepadNext/resources.qrc @@ -0,0 +1,47 @@ +<RCC> + <qresource prefix="/"> + <file>icons/newfile.png</file> + <file>icons/saved.png</file> + <file>icons/unsaved.png</file> + <file>icons/openFile.png</file> + <file>icons/saveAll.png</file> + <file>icons/closeAll.png</file> + <file>icons/closeFile.png</file> + <file>icons/copy.png</file> + <file>icons/cut.png</file> + <file>icons/paste.png</file> + <file>icons/redo.png</file> + <file>icons/undo.png</file> + <file>icons/zoomIn.png</file> + <file>icons/zoomOut.png</file> + <file>icons/indentGuide.png</file> + <file>icons/invisibleChar.png</file> + <file>icons/wrap.png</file> + <file>icons/find.png</file> + <file>stylesheets/npp.css</file> + <file>stylesheets/npp-dark.css</file> + <file>icons/findReplace.png</file> + <file>icons/readonly.png</file> + <file>icons/startRecord.png</file> + <file>icons/stopRecord.png</file> + <file>icons/playRecord.png</file> + <file>icons/playRecord_m.png</file> + <file>icons/saveRecord.png</file> + <file>icons/text_indent.png</file> + <file>icons/text_indent_remove.png</file> + <file>icons/arrow_refresh.png</file> + <file>icons/bin_closed.png</file> + <file>icons/printer.png</file> + <file>icons/NotepadNext.png</file> + <file>icons/cog.png</file> + <file>icons/table_delete.png</file> + <file>icons/table_row_delete.png</file> + <file>icons/table_row_insert.png</file> + <file>icons/arrow_down.png</file> + <file>icons/arrow_up.png</file> + <file>icons/table_edit.png</file> + <file>icons/application_osx_terminal.png</file> + <file>icons/folder_go.png</file> + <file>icons/wrapindicator.png</file> + </qresource> +</RCC> diff --git a/src/NotepadNext/scripts.qrc b/src/NotepadNext/scripts.qrc new file mode 100644 index 000000000..83e1fc19b --- /dev/null +++ b/src/NotepadNext/scripts.qrc @@ -0,0 +1,90 @@ +<RCC> + <qresource prefix="/"> + <file>scripts/init.lua</file> + <file>languages/cpp.lua</file> + <file>languages/lua.lua</file> + <file>languages/text.lua</file> + <file>languages/python.lua</file> + <file>languages/actionscript.lua</file> + <file>languages/ada.lua</file> + <file>languages/asm.lua</file> + <file>languages/asn1.lua</file> + <file>languages/asp.lua</file> + <file>languages/autoit.lua</file> + <file>languages/avs.lua</file> + <file>languages/baanc.lua</file> + <file>languages/bash.lua</file> + <file>languages/batch.lua</file> + <file>languages/blitzbasic.lua</file> + <file>languages/c.lua</file> + <file>languages/caml.lua</file> + <file>languages/cmake.lua</file> + <file>languages/cobol.lua</file> + <file>languages/coffeescript.lua</file> + <file>languages/cs.lua</file> + <file>languages/csound.lua</file> + <file>languages/css.lua</file> + <file>languages/scss.lua</file> + <file>languages/d.lua</file> + <file>languages/diff.lua</file> + <file>languages/erlang.lua</file> + <file>languages/escript.lua</file> + <file>languages/forth.lua</file> + <file>languages/fortran.lua</file> + <file>languages/fortran77.lua</file> + <file>languages/freebasic.lua</file> + <file>languages/gui4cli.lua</file> + <file>languages/haskell.lua</file> + <file>languages/html.lua</file> + <file>languages/ihex.lua</file> + <file>languages/ini.lua</file> + <file>languages/inno.lua</file> + <file>languages/java.lua</file> + <file>languages/javascript.lua</file> + <file>languages/json.lua</file> + <file>languages/kix.lua</file> + <file>languages/latex.lua</file> + <file>languages/lisp.lua</file> + <file>languages/less.lua</file> + <file>languages/makefile.lua</file> + <file>languages/matlab.lua</file> + <file>languages/mmixal.lua</file> + <file>languages/nfo.lua</file> + <file>languages/nimrod.lua</file> + <file>languages/nncrontab.lua</file> + <file>languages/nsis.lua</file> + <file>languages/objc.lua</file> + <file>languages/oscript.lua</file> + <file>languages/pascal.lua</file> + <file>languages/perl.lua</file> + <file>languages/php.lua</file> + <file>languages/postscript.lua</file> + <file>languages/powershell.lua</file> + <file>languages/props.lua</file> + <file>languages/purebasic.lua</file> + <file>languages/r.lua</file> + <file>languages/rc.lua</file> + <file>languages/rebol.lua</file> + <file>languages/registry.lua</file> + <file>languages/ruby.lua</file> + <file>languages/rust.lua</file> + <file>languages/scheme.lua</file> + <file>languages/smalltalk.lua</file> + <file>languages/spice.lua</file> + <file>languages/sql.lua</file> + <file>languages/srec.lua</file> + <file>languages/swift.lua</file> + <file>languages/tcl.lua</file> + <file>languages/tehex.lua</file> + <file>languages/tex.lua</file> + <file>languages/txt2tags.lua</file> + <file>languages/vb.lua</file> + <file>languages/verilog.lua</file> + <file>languages/vhdl.lua</file> + <file>languages/visualprolog.lua</file> + <file>languages/xml.lua</file> + <file>languages/yaml.lua</file> + <file>languages/go.lua</file> + <file>languages/markdown.lua</file> + </qresource> +</RCC> diff --git a/src/NotepadNext/scripts/init.lua b/src/NotepadNext/scripts/init.lua new file mode 100644 index 000000000..cea0acb34 --- /dev/null +++ b/src/NotepadNext/scripts/init.lua @@ -0,0 +1,140 @@ +function rgb(x) + return ((x & 0xFF) << 16) | (x & 0xFF00) | ((x & 0xFF0000) >> 16) +end + +function starts_with(str, start) + return str:sub(1, #start) == start +end + +function detectLanguageFromContents(contents) + for name, L in pairs(languages) do + if L.first_line then + for _, pattern in ipairs(L.first_line) do + if string.match(contents, pattern) then + return name + end + end + end + end + return "Text" +end + +function FilterForLanguage(name) + local extensions = {} + local language_definition = languages[name] + + if not language_definition.extensions then + return nil + end + + for _, ext in ipairs(language_definition.extensions) do + if #ext > 0 then + extensions[#extensions + 1] = "*." .. ext + end + end + + return name .. " Files (" .. table.concat(extensions, " ") .. ")" +end + +function DialogFilters() + local filters = {} + + for name, L in pairs(languages) do + local filter = FilterForLanguage(name) + if filter then + filters[#filters + 1] = filter + end + end + + table.sort(filters, function (a, b) return a:lower() < b:lower() end) + table.insert(filters, 1, "All Files (*)") + + return table.concat(filters, ";;") +end + +languages = {} +languages["ActionScript"] = require("actionscript") +languages["ADA"] = require("ada") +languages["Assembly"] = require("asm") +languages["ASN.1"] = require("asn1") +languages["asp"] = require("asp") +languages["autoIt"] = require("autoit") +languages["AviSynth"] = require("avs") +languages["BaanC"] = require("baanc") +languages["bash"] = require("bash") +languages["Batch"] = require("batch") +languages["BlitzBasic"] = require("blitzbasic") +languages["C"] = require("c") +languages["Caml"] = require("caml") +languages["CMakeFile"] = require("cmake") +languages["COBOL"] = require("cobol") +languages["Csound"] = require("csound") +languages["CoffeeScript"] = require("coffeescript") +languages["C++"] = require("cpp") +languages["C#"] = require("cs") +languages["CSS"] = require("css") +languages["SCSS"] = require("scss") +languages["D"] = require("d") +languages["DIFF"] = require("diff") +languages["Erlang"] = require("erlang") +languages["ESCRIPT"] = require("escript") +languages["Forth"] = require("forth") +languages["Fortran (free form)"] = require("fortran") +languages["Fortran (fixed form)"] = require("fortran77") +languages["FreeBasic"] = require("freebasic") +languages["GUI4CLI"] = require("gui4cli") +languages["Go"] = require("go") +languages["Haskell"] = require("haskell") +languages["HTML"] = require("html") +languages["ini file"] = require("ini") +languages["InnoSetup"] = require("inno") +languages["Intel HEX"] = require("ihex") +languages["Java"] = require("java") +languages["JavaScript"] = require("javascript") +languages["JSON"] = require("json") +languages["KiXtart"] = require("kix") +languages["LISP"] = require("lisp") +languages["LaTeX"] = require("latex") +languages["Lua"] = require("lua") +languages["Less"] = require("less") +languages["Makefile"] = require("makefile") +languages["Markdown"] = require("markdown") +languages["Matlab"] = require("matlab") +languages["MMIXAL"] = require("mmixal") +languages["Nimrod"] = require("nimrod") +languages["extended crontab"] = require("nncrontab") +languages["Dos Style"] = require("nfo") +languages["NSIS"] = require("nsis") +languages["OScript"] = require("oscript") +languages["Objective-C"] = require("objc") +languages["Pascal"] = require("pascal") +languages["Perl"] = require("perl") +languages["PHP"] = require("php") +languages["Postscript"] = require("postscript") +languages["PowerShell"] = require("powershell") +languages["Properties file"] = require("props") +languages["PureBasic"] = require("purebasic") +languages["Python"] = require("python") +languages["R"] = require("r") +languages["REBOL"] = require("rebol") +languages["registry"] = require("registry") +languages["RC"] = require("rc") +languages["Ruby"] = require("ruby") +languages["Rust"] = require("rust") +languages["Scheme"] = require("scheme") +languages["Smalltalk"] = require("smalltalk") +languages["spice"] = require("spice") +languages["SQL"] = require("sql") +languages["S-Record"] = require("srec") +languages["Swift"] = require("swift") +languages["TCL"] = require("tcl") +languages["Tektronix extended HEX"] = require("tehex") +languages["TeX"] = require("tex") +languages["Text"] = require("text") +languages["VB / VBS"] = require("vb") +languages["txt2tags"] = require("txt2tags") +languages["Verilog"] = require("verilog") +languages["VHDL"] = require("vhdl") +languages["Visual Prolog"] = require("visualprolog") +languages["XML"] = require("xml") +languages["YAML"] = require("yaml") diff --git a/src/NotepadNext/stylesheets/npp-dark.css b/src/NotepadNext/stylesheets/npp-dark.css new file mode 100644 index 000000000..cdbfbf18c --- /dev/null +++ b/src/NotepadNext/stylesheets/npp-dark.css @@ -0,0 +1,54 @@ +/* Dark mode further tweak, in addition to qdarkstyle */ +/* Separate from qdarkstyle so that qdarkstyle upgrade will not override it */ + +/* NotepadNext tabbar configuration ---------------------------------------- + +----------------------------------------------------------------------------*/ +ads--CDockWidgetTab[activeTab="true"] { + /*background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0 + palette(window), stop:1 palette(light));*/ + background: palette(highlight); + color: palette(foreground); +} + +ads--CDockWidgetTab QLabel { + color: palette(dark); +} + +ads--CDockWidgetTab[activeTab="true"] QLabel { + color: palette(foreground); + background: palette(highlight); +} + +ads--CDockWidgetTab { + /* Make tab icons smaller */ + /*qproperty-iconSize: 8px 8px;*/ +} + +#dockWidgetTabLabel { + margin: 0px; + /* Fix tiltle text truncation at header/tail */ + padding: 0px; +} + +#tabCloseButton { + margin: 0px; + padding: 0x; +} + +/* changed for NotepadNext - 'Close without save' button */ +/*QDialogButtonBox QPushButton { + min-width: 160px; +}*/ + +QMessageBox > QDialogButtonBox > QPushButton[text="Close without Saving"] { + /* Avoid save file dialog on Linux close button long text truncation */ + min-width: 160px; +} + +QAbstractScrollArea { + /* Fix NotepadNext editor first character cut-off issue */ + margin-left: -2px; + /* Fix NotepadNext editor first line cut-off issue on Linux */ + margin-top: -2px; +} diff --git a/src/NotepadNext/stylesheets/npp.css b/src/NotepadNext/stylesheets/npp.css new file mode 100644 index 000000000..cc0aa0cfd --- /dev/null +++ b/src/NotepadNext/stylesheets/npp.css @@ -0,0 +1,77 @@ +QStatusBar { + border-top: 1px solid darkgray; +} + +ads--CDockWidgetTab ads--CElidingLabel { + color : black; +} + +ads--CDockWidgetTab { + background: rgb(192, 192, 192); + margin-top: 2px; + border-left: 1px solid white; + border-top: 2px solid white; + border-right: 2px solid gray; + padding: 2px 2px 0px 2px; + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} + +ads--CDockWidgetTab[activeTab="true"] +{ + background: rgb(240, 240, 240); + border-top: 4px solid rgb(255, 202, 176); + padding-bottom: 2px; + margin-top: 1px; +} + +ads--CDockWidgetTab[focused="true"] +{ + background: rgb(240, 240, 240); + border-top: 4px solid orange; + padding-bottom: 2px; + margin-top: 1px; +} + +ads--CDockWidgetTab:hover[activeTab="false"] { + background: rgb(210, 210, 210); +} + +ads--CDockAreaTitleBar +{ + background: transparent; + border-bottom: 1px solid darkgray; + padding-bottom: 0px; +} + +ads--CDockWidgetTab[activeTab="false"] QLabel { + color: gray; +} + +#tabCloseButton +{ + background: rgba(0, 0, 0, 16); + margin-bottom: 1px; + margin-left: 4px; + border: none; + padding: 0px -2px; +} + +#tabCloseButton:hover +{ + border: 1px solid rgba(0, 0, 0, 32); + background-color: rgb(251, 115, 115); + color: green; +} + +#tabCloseButton:pressed +{ + background: red; +} + +#QuickFindWidget { + border-left: 1px solid darkgray; + border-right: 1px solid darkgray; + border-bottom: 3px solid blue; + background: palette(window); +} diff --git a/src/NotepadNext/widgets/EditorInfoStatusBar.cpp b/src/NotepadNext/widgets/EditorInfoStatusBar.cpp new file mode 100644 index 000000000..6809d7a2d --- /dev/null +++ b/src/NotepadNext/widgets/EditorInfoStatusBar.cpp @@ -0,0 +1,184 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + */ + + +#include "EditorInfoStatusBar.h" +#include "MainWindow.h" +#include "StatusLabel.h" + + +EditorInfoStatusBar::EditorInfoStatusBar(QMainWindow *window) : + QStatusBar(window) +{ + // Set up the status bar + docType = new StatusLabel(); + addWidget(docType, 1); + + docSize = new StatusLabel(200); + addPermanentWidget(docSize, 0); + + docPos = new StatusLabel(250); + addPermanentWidget(docPos, 0); + + eolFormat = new StatusLabel(100); + addPermanentWidget(eolFormat, 0); + + unicodeType = new StatusLabel(125); + addPermanentWidget(unicodeType, 0); + + overType = new StatusLabel(25); + addPermanentWidget(overType, 0); + + /* + docType->setContextMenuPolicy(Qt::CustomContextMenu); + connect(docType, &QLabel::customContextMenuRequested, [=](const QPoint &pos) { + ui->menuLanguage->popup(docType->mapToGlobal(pos)); + }); + + eolFormat->setContextMenuPolicy(Qt::CustomContextMenu); + connect(eolFormat, &QLabel::customContextMenuRequested, [=](const QPoint &pos) { + ui->menuEOLConversion->popup(eolFormat->mapToGlobal(pos)); + }); + */ + + MainWindow *w = qobject_cast<MainWindow *>(window); + + connect(w, &MainWindow::editorActivated, this, &EditorInfoStatusBar::connectToEditor); + + connect(qobject_cast<StatusLabel*>(overType), &StatusLabel::clicked, w, [=]() { + ScintillaNext *editor = w->currentEditor(); + editor->editToggleOvertype(); + updateOverType(editor); + }); +} + +void EditorInfoStatusBar::refresh(ScintillaNext *editor) +{ + updateDocumentSize(editor); + updateSelectionInfo(editor); + updateLanguage(editor); + updateEol(editor); + updateEncoding(editor); + updateOverType(editor); +} + +void EditorInfoStatusBar::connectToEditor(ScintillaNext *editor) +{ + // Remove any previous connections + disconnect(editorUiUpdated); + disconnect(documentLexerChanged); + + // Connect to the new editor + editorUiUpdated = connect(editor, &ScintillaNext::updateUi, this, &EditorInfoStatusBar::editorUpdated); + documentLexerChanged = connect(editor, &ScintillaNext::lexerChanged, this, [=]() { updateLanguage(editor); }); + + refresh(editor); +} + +void EditorInfoStatusBar::editorUpdated(Scintilla::Update updated) +{ + ScintillaNext *editor = qobject_cast<ScintillaNext *>(sender()); + + if (Scintilla::FlagSet(updated, Scintilla::Update::Content)) { + updateDocumentSize(editor); + } + + if (Scintilla::FlagSet(updated, Scintilla::Update::Content) || Scintilla::FlagSet(updated, Scintilla::Update::Selection)) { + updateSelectionInfo(editor); + } +} + +void EditorInfoStatusBar::updateDocumentSize(ScintillaNext *editor) +{ + QString sizeText = tr("Length: %L1 Lines: %L2").arg(editor->length()).arg(editor->lineCount()); + docSize->setText(sizeText); +} + +void EditorInfoStatusBar::updateSelectionInfo(ScintillaNext *editor) +{ + QString selectionText; + + if (editor->selections() > 1) { + selectionText = tr("Sel: N/A"); + } + else { + int start = editor->selectionStart(); + int end = editor->selectionEnd(); + int lines = editor->lineFromPosition(end) - editor->lineFromPosition(start); + + if (end > start) + lines++; + + selectionText = tr("Sel: %L1 | %L2").arg(editor->countCharacters(start, end)).arg(lines); + } + + const int pos = editor->currentPos(); + QString positionText = tr("Ln: %L1 Col: %L2 ").arg(editor->lineFromPosition(pos) + 1).arg(editor->column(pos) + 1); + docPos->setText(positionText + selectionText); +} + +void EditorInfoStatusBar::updateLanguage(ScintillaNext *editor) +{ + docType->setText(editor->languageName); +} + + +void EditorInfoStatusBar::updateEol(ScintillaNext *editor) +{ + // No good way to keep these in sync with the Main Window menu items :( + + switch(editor->eOLMode()) { + case SC_EOL_CR: + eolFormat->setText(tr("Macintosh (CR)")); + break; + case SC_EOL_CRLF: + eolFormat->setText(tr("Windows (CR LF)")); + break; + case SC_EOL_LF: + eolFormat->setText(tr("Unix (LF)")); + break; + } +} + +void EditorInfoStatusBar::updateEncoding(ScintillaNext *editor) +{ + switch(editor->codePage()) { + case 0: + unicodeType->setText(tr("ANSI")); + break; + case SC_CP_UTF8: + unicodeType->setText(tr("UTF-8")); + break; + default: + unicodeType->setText(QString::number(editor->codePage())); + break; + } +} + +void EditorInfoStatusBar::updateOverType(ScintillaNext *editor) +{ + bool overtype = editor->overtype(); + if (overtype) { + //: This is a short abbreviation to indicate characters will be replaced when typing + overType->setText(tr("OVR")); + } + else { + //: This is a short abbreviation to indicate characters will be inserted when typing + overType->setText(tr("INS")); + } +} diff --git a/src/NotepadNext/widgets/EditorInfoStatusBar.h b/src/NotepadNext/widgets/EditorInfoStatusBar.h new file mode 100644 index 000000000..ad75bbdd8 --- /dev/null +++ b/src/NotepadNext/widgets/EditorInfoStatusBar.h @@ -0,0 +1,65 @@ +/* + * This file is part of Notepad Next. + * Copyright 2022 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + */ + + +#ifndef EDITORINFOSTATUSBAR_H +#define EDITORINFOSTATUSBAR_H + +#include <QStatusBar> + +#include "ScintillaTypes.h" + + +class QLabel; +class QMainWindow; +class ScintillaNext; + +class EditorInfoStatusBar : public QStatusBar +{ + Q_OBJECT + +public: + explicit EditorInfoStatusBar(QMainWindow *window); + + void refresh(ScintillaNext *editor); + +private slots: + void connectToEditor(ScintillaNext *editor); + + void editorUpdated(Scintilla::Update updated); + + void updateDocumentSize(ScintillaNext *editor); + void updateSelectionInfo(ScintillaNext *editor); + void updateLanguage(ScintillaNext *editor); + void updateEol(ScintillaNext *editor); + void updateEncoding(ScintillaNext *editor); + void updateOverType(ScintillaNext *editor); + +private: + QLabel *docType; + QLabel *docSize; + QLabel *docPos; + QLabel *unicodeType; + QLabel *eolFormat; + QLabel *overType; + + QMetaObject::Connection editorUiUpdated; + QMetaObject::Connection documentLexerChanged; +}; + +#endif // EDITORINFOSTATUSBAR_H diff --git a/src/NotepadNext/widgets/StatusLabel.cpp b/src/NotepadNext/widgets/StatusLabel.cpp new file mode 100644 index 000000000..fecae7fc9 --- /dev/null +++ b/src/NotepadNext/widgets/StatusLabel.cpp @@ -0,0 +1,21 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + */ + + +#include "StatusLabel.h" + diff --git a/src/NotepadNext/widgets/StatusLabel.h b/src/NotepadNext/widgets/StatusLabel.h new file mode 100644 index 000000000..17dcfa34b --- /dev/null +++ b/src/NotepadNext/widgets/StatusLabel.h @@ -0,0 +1,67 @@ +/* + * This file is part of Notepad Next. + * Copyright 2019 Justin Dailey + * + * Notepad Next 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, either version 3 of the License, or + * (at your option) any later version. + * + * Notepad Next 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. + * + * You should have received a copy of the GNU General Public License + * along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + */ + + +#ifndef STATUSLABEL_H +#define STATUSLABEL_H + +#include <QLabel> +#include <QMouseEvent> + + +class ClickableLabel : public QLabel +{ + Q_OBJECT + +public: + explicit ClickableLabel(QWidget *parent=Q_NULLPTR, Qt::WindowFlags f=Qt::WindowFlags()) : QLabel(parent, f) {} + explicit ClickableLabel(const QString &text, QWidget *parent=Q_NULLPTR, Qt::WindowFlags f=Qt::WindowFlags()) : QLabel(text, parent, f) {} + +signals: + void clicked(); + +protected: + void mouseReleaseEvent(QMouseEvent *event) override { Q_UNUSED(event); emit clicked(); } + void mouseDoubleClickEvent(QMouseEvent *event) override { emit customContextMenuRequested(event->pos()); } +}; + + +class StatusLabel : public ClickableLabel +{ + Q_OBJECT + +public: + explicit StatusLabel(int size = 200, QWidget *parent = 0) : ClickableLabel(parent), preferredSize(size) { + // Since these get set a lot and plain text is always used go ahead and set the format + setTextFormat(Qt::PlainText); + } + +protected: + QSize sizeHint() const override { + QSize size = ClickableLabel::sizeHint(); + size.setWidth(preferredSize); + return size; + } + + QSize minimumSizeHint() const override { return QSize(); } + +private: + int preferredSize; +}; + +#endif // STATUSLABEL_H diff --git a/src/QSimpleUpdater b/src/QSimpleUpdater new file mode 160000 index 000000000..62e0ce7dd --- /dev/null +++ b/src/QSimpleUpdater @@ -0,0 +1 @@ +Subproject commit 62e0ce7dde4c76e7533f2f0ee53f19ee1690c8dd diff --git a/src/Version.pri b/src/Version.pri new file mode 100644 index 000000000..ef934ce49 --- /dev/null +++ b/src/Version.pri @@ -0,0 +1,19 @@ +# This file is part of Notepad Next. +# Copyright 2019 Justin Dailey +# +# Notepad Next 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, either version 3 of the License, or +# (at your option) any later version. +# +# Notepad Next 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. +# +# You should have received a copy of the GNU General Public License +# along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + + +APP_VERSION = "0.8" +APP_COPYRIGHT = "Copyright 2019-2024 Justin Dailey" diff --git a/src/ads b/src/ads new file mode 160000 index 000000000..59b4dfb89 --- /dev/null +++ b/src/ads @@ -0,0 +1 @@ +Subproject commit 59b4dfb89c0c9c0e6035fe580088432312ed2d09 diff --git a/src/ads.pri b/src/ads.pri new file mode 100644 index 000000000..063d59683 --- /dev/null +++ b/src/ads.pri @@ -0,0 +1,91 @@ +# This file is part of Notepad Next. +# Copyright 2020 Justin Dailey +# +# Notepad Next 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, either version 3 of the License, or +# (at your option) any later version. +# +# Notepad Next 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. +# +# You should have received a copy of the GNU General Public License +# along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + +QT += core gui widgets + +windows { + # MinGW + *-g++* { + QMAKE_CXXFLAGS += -Wall -Wextra -pedantic + } + # MSVC + *-msvc* { + QMAKE_CXXFLAGS += /utf-8 + } +} + +RESOURCES += $$PWD/ads/src/ads.qrc + +HEADERS += \ + $$PWD/ads/src/ads_globals.h \ + $$PWD/ads/src/DockAreaWidget.h \ + $$PWD/ads/src/DockAreaTabBar.h \ + $$PWD/ads/src/DockContainerWidget.h \ + $$PWD/ads/src/DockManager.h \ + $$PWD/ads/src/DockWidget.h \ + $$PWD/ads/src/DockWidgetTab.h \ + $$PWD/ads/src/DockingStateReader.h \ + $$PWD/ads/src/FloatingDockContainer.h \ + $$PWD/ads/src/FloatingDragPreview.h \ + $$PWD/ads/src/DockOverlay.h \ + $$PWD/ads/src/DockSplitter.h \ + $$PWD/ads/src/DockAreaTitleBar_p.h \ + $$PWD/ads/src/DockAreaTitleBar.h \ + $$PWD/ads/src/ElidingLabel.h \ + $$PWD/ads/src/IconProvider.h \ + $$PWD/ads/src/DockComponentsFactory.h \ + $$PWD/ads/src/DockFocusController.h \ + $$PWD/ads/src/AutoHideDockContainer.h \ + $$PWD/ads/src/AutoHideSideBar.h \ + $$PWD/ads/src/AutoHideTab.h \ + $$PWD/ads/src/PushButton.h \ + $$PWD/ads/src/ResizeHandle.h + + +SOURCES += \ + $$PWD/ads/src/ads_globals.cpp \ + $$PWD/ads/src/DockAreaWidget.cpp \ + $$PWD/ads/src/DockAreaTabBar.cpp \ + $$PWD/ads/src/DockContainerWidget.cpp \ + $$PWD/ads/src/DockManager.cpp \ + $$PWD/ads/src/DockWidget.cpp \ + $$PWD/ads/src/DockingStateReader.cpp \ + $$PWD/ads/src/DockWidgetTab.cpp \ + $$PWD/ads/src/FloatingDockContainer.cpp \ + $$PWD/ads/src/FloatingDragPreview.cpp \ + $$PWD/ads/src/DockOverlay.cpp \ + $$PWD/ads/src/DockSplitter.cpp \ + $$PWD/ads/src/DockAreaTitleBar.cpp \ + $$PWD/ads/src/ElidingLabel.cpp \ + $$PWD/ads/src/IconProvider.cpp \ + $$PWD/ads/src/DockComponentsFactory.cpp \ + $$PWD/ads/src/DockFocusController.cpp \ + $$PWD/ads/src/AutoHideDockContainer.cpp \ + $$PWD/ads/src/AutoHideSideBar.cpp \ + $$PWD/ads/src/AutoHideTab.cpp \ + $$PWD/ads/src/PushButton.cpp \ + $$PWD/ads/src/ResizeHandle.cpp + + +unix:!macx { + HEADERS += $$PWD/ads/src/linux/FloatingWidgetTitleBar.h + SOURCES += $$PWD/ads/src/linux/FloatingWidgetTitleBar.cpp + LIBS += -lxcb + QT += gui-private +} + + +INCLUDEPATH += $$PWD/ads/src/ diff --git a/src/editorconfig-core-qt b/src/editorconfig-core-qt new file mode 160000 index 000000000..52820d597 --- /dev/null +++ b/src/editorconfig-core-qt @@ -0,0 +1 @@ +Subproject commit 52820d59769fcba6d0ed94f685406c0383fe1a30 diff --git a/src/i18n.pri b/src/i18n.pri new file mode 100644 index 000000000..fd6111a4e --- /dev/null +++ b/src/i18n.pri @@ -0,0 +1,43 @@ +# This file is part of Notepad Next. +# Copyright 2020 Justin Dailey +# +# Notepad Next 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, either version 3 of the License, or +# (at your option) any later version. +# +# Notepad Next 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. +# +# You should have received a copy of the GNU General Public License +# along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + +## [i18n.pri] Configuration related to internationalization. + +CONFIG += lrelease embed_translations + +LOCALES = \ + zh_CN \ + zh_TW \ + sv_SE \ + uk_UA \ + tr_TR \ + pl_PL \ + ru_RU \ + pt_PT + +for(LOCALE, LOCALES) { + # The application translation file + TRANSLATIONS += ../../i18n/NotepadNext_$${LOCALE}.ts + + # Extra translation files that include both the language and translation + EXTRA_TRANSLATIONS += $$files($$[QT_INSTALL_TRANSLATIONS]/qt_$${LOCALE}.qm) + EXTRA_TRANSLATIONS += $$files($$[QT_INSTALL_TRANSLATIONS]/qtbase_$${LOCALE}.qm) + + # Check for files without the territory specified + LANGUAGE = $$replace(LOCALE, "(..).*", "\\1") + EXTRA_TRANSLATIONS += $$files($$[QT_INSTALL_TRANSLATIONS]/qt_$${LANGUAGE}.qm) + EXTRA_TRANSLATIONS += $$files($$[QT_INSTALL_TRANSLATIONS]/qtbase_$${LANGUAGE}.qm) +} diff --git a/src/lexilla.pri b/src/lexilla.pri new file mode 100644 index 000000000..2d0d4ddcf --- /dev/null +++ b/src/lexilla.pri @@ -0,0 +1,33 @@ +# This file is part of Notepad Next. +# Copyright 2021 Justin Dailey +# +# Notepad Next 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, either version 3 of the License, or +# (at your option) any later version. +# +# Notepad Next 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. +# +# You should have received a copy of the GNU General Public License +# along with Notepad Next. If not, see <https://www.gnu.org/licenses/>. + + + +HEADERS += \ + $$PWD/lexilla/include/Lexilla.h \ + $$files($$PWD/lexilla/lexlib/*.h, false) + +unix { + LIBS += -ldl +} + +SOURCES += \ + $$PWD/lexilla/src/Lexilla.cxx \ + $$PWD/lexilla/access/LexillaAccess.cxx \ + $$files($$PWD/lexilla/lexlib/*.cxx, false) \ + $$files($$PWD/lexilla/lexers/*.cxx, false) + +INCLUDEPATH += $$PWD/lexilla/access/ $$PWD/lexilla/lexlib/ $$PWD/lexilla/include/ diff --git a/src/lexilla/.gitattributes b/src/lexilla/.gitattributes new file mode 100644 index 000000000..4864626b9 --- /dev/null +++ b/src/lexilla/.gitattributes @@ -0,0 +1,88 @@ +* -text +**.cxx text +**.cpp text +**.c text +**.h text +**.hpp text +**.m text +**.mm text +**.iface text +**.template text +**.mk text +**.mk text +**.py text +**.rc text +**.css text +**.html text +**.bat text +**.bsh text +**.zsh text +**.mak text +**.def text +**.manifest text +**.properties text +**.props text +**.session text +**.styled text +**.folded text +**.adoc text +**.asp text +**.aspx text +**.php text +**.vb text +**.vbs text +**.asm text +**.cob text +**.cmake text +**.d text +**.diff text +**.erl text +**.f text +**.gd text +**.gui text +**.iss text +**.jl text +**.json text +**.lua text +**.m3 text +**.matlab text +**.ml text +**.nim text +**.octave text +**.p text +**.pl text +**.p6 text +**.ps1 text +**.r text +**.rb text +**.rs text +**.sql text +**.tcl text +**.toml text +**.tsql text +**.err text +**.mms text +**.tex text +**.fs text +**.vh text +**.vhd text +**.x12 text +**.yaml text +**.md text +**.txt text +**.pch text +**.hg* text +**.dsp text +**.pbxproj text +**.plist text +**.xcworkspacedata text +**.pro text +**.gen text +**makefile text +**.bmp binary +**.cur binary +**.ico binary +**.jpg binary +**.png binary +**.sh text eol=lf +tgzsrc text eol=lf diff --git a/src/lexilla/.gitignore b/src/lexilla/.gitignore new file mode 100644 index 000000000..725ec83cc --- /dev/null +++ b/src/lexilla/.gitignore @@ -0,0 +1,71 @@ +*.o +*.a +*.lib +*.obj +*.iobj +__pycache__ +*.pyc +*.dll +*.so +*.dylib +*.framework +*.pyd +*.exe +*.exp +*.lib +*.pdb +*.ipdb +*.res +*.bak +*.sbr +*.suo +*.aps +*.sln +*.vcxproj.* +*.idb +*.bsc +*.intermediate.manifest +*.lastbuildstate +*.nativecodeanalysis.xml +*.cache +*.ilk +*.ncb +*.tlog +*.sdf +gtk/*.plist +win32/*.plist +*.opt +*.plg +*.pbxbtree +*.mode1v3 +*.pbxuser +*.pbproj +*.tgz +*.log +*.xcbkptlist +*.xcuserstate +xcuserdata/ +*.xcsettings +xcschememanagement.plist +.DS_Store +test/TestLexers +Release +Debug +x64 +ARM64 +cocoa/build +cocoa/ScintillaFramework/build +cocoa/ScintillaTest/build +macosx/SciTest/build +*.cppcheck +*.pro.user +.qmake.stash +cov-int +.vs +meson-private +meson-logs +build.ninja +.ninja* +compile_commands.json +.vscode/ +VTune Profiler Results/ diff --git a/src/lexilla/.travis.yml b/src/lexilla/.travis.yml new file mode 100644 index 000000000..d6addc195 --- /dev/null +++ b/src/lexilla/.travis.yml @@ -0,0 +1,42 @@ +# Build Lexilla with gcc and clang on Linux, macOS, and Windows +# Test Lexilla with gcc and clang on Linux and macOS +# Windows has older versions of libraries so can't compile std::filesystem +# with gcc or std::string::starts_with with clang. +# On macOS, gcc is a synonym for clang so exclude gcc. +os: + - linux + - osx + - windows + +dist: focal + +osx_image: xcode12.3 + +language: cpp + +jobs: + exclude: + - os: osx + compiler: gcc + +install: + - cd .. + - wget --no-verbose https://www.scintilla.org/scintilla500.zip + - if [ "$TRAVIS_OS_NAME" = "windows" ]; then 7z x scintilla500.zip ; else unzip scintilla500.zip ; fi + - cd lexilla + +compiler: + - gcc + - clang + +script: + - if [ "$TRAVIS_OS_NAME" = "windows" ]; then MAKER="mingw32-make windir=1" ; else MAKER="make" ; fi + - (cd src && $MAKER DEBUG=1) + - cd test + - if [ "$TRAVIS_OS_NAME" != "windows" ]; then make DEBUG=1 test ; fi + - (cd unit && $MAKER DEBUG=1 test) + - cd .. + - cd examples + - (cd CheckLexilla && $MAKER DEBUG=1 check) + - (cd SimpleLexer && $MAKER DEBUG=1 check) + - cd .. diff --git a/src/lexilla/CONTRIBUTING b/src/lexilla/CONTRIBUTING new file mode 100644 index 000000000..01870a9a7 --- /dev/null +++ b/src/lexilla/CONTRIBUTING @@ -0,0 +1,42 @@ +Lexilla is on GitHub at https://github.com/ScintillaOrg/lexilla + +Bugs, fixes and features should be posted to the Issue Tracker +https://github.com/ScintillaOrg/lexilla/issues + +Patches should include test cases. Add a test case file in +lexilla/test/examples/<language> and run the test program in +lexilla/test. +The result will be new files with ".styled.new" and ".folded.new" +appended containing lexing or folding results. +For lexing, there are brace surrounded style numbers for each style +start as markup: +{5}import{0} {11}contextlib{0} + +For folding, there are 4 columns of folding results preceding the example text: + 2 400 0 + --[[ coding:UTF-8 + 0 402 0 | comment ]] +See the test/README file for more explanation of the folding results. + +To build lexilla and the tests with gcc there are Windows batch +and Unix shell files scripts/RunTest.bat scripts/RunTest.sh. +Check the result of the .new files and, if correct, rename replacing +".styled.new" with ".styled" and ".folded.new" with ".folded". +Run the tests again and success should be reported. +Include the .styled and .folded files in the patch. +Including test cases ensures that the change won't be undone by +other changes in the future and clarifies the intentions of the author. + +Either send unified diffs (or patch files) or zip archives with whole files. +Mercurial/Git patch files are best as they include author information and commit +messages. + +Questions should go to the scintilla-interest mailing list +https://groups.google.com/forum/#!forum/scintilla-interest + +Code should follow the guidelines at +https://www.scintilla.org/SciCoding.html + +Lexilla is on GitHub so use its facilities rather than SourceForge which is +the home of Scintilla. +The neilh @ scintilla.org account receives much spam and is only checked +occasionally. Almost all Scintilla mail should go to the mailing list. diff --git a/src/lexilla/License.txt b/src/lexilla/License.txt new file mode 100644 index 000000000..e93ac62f2 --- /dev/null +++ b/src/lexilla/License.txt @@ -0,0 +1,20 @@ +License for Lexilla, Scintilla, and SciTE + +Copyright 1998-2021 by Neil Hodgson <neilh@scintilla.org> + +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. + +NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/src/lexilla/README b/src/lexilla/README new file mode 100644 index 000000000..d2a1d566d --- /dev/null +++ b/src/lexilla/README @@ -0,0 +1,49 @@ +README for Lexilla library. + +The Lexilla library contains a set of lexers and folders that provides support for +programming, mark-up, and data languages for the Scintilla source code editing +component. + +Lexilla is made available as both a shared library and static library. +The shared library is called liblexilla.so / liblexilla.dylib / lexilla.dll on Linux / macOS / +Windows. +The static library is called liblexilla.a when built with GCC or Clang and liblexilla.lib +when built with MSVC. + +Lexilla is developed on Windows, Linux, and macOS and requires a C++17 compiler. +It may work on other Unix platforms like BSD but that is not a development focus. +MSVC 2019.4, GCC 9.0, Clang 9.0, and Apple Clang 11.0 are known to work. + +MSVC is only available on Windows. + +GCC and Clang work on Windows and Linux. + +On macOS, only Apple Clang is available. + +Lexilla requires some headers from Scintilla to build and expects a directory named +"scintilla" containing a copy of Scintilla 5+ to be a peer of the Lexilla top level +directory conventionally called "lexilla". + +To use GCC, run lexilla/src/makefile: + make + +To use Clang, run lexilla/test/makefile: + make CLANG=1 +On macOS, CLANG is set automatically so this can just be + make + +To use MSVC, run lexilla/test/lexilla.mak: + nmake -f lexilla.mak + +To build a debugging version of the library, add DEBUG=1 to the command: + make DEBUG=1 + +The built libraries are copied into lexilla/bin. + +Lexilla relies on a list of lexers from the lexilla/lexers directory. If any changes are +made to the set of lexers then source and build files can be regenerated with the +lexilla/scripts/LexillaGen.py script which requires Python 3 and is tested with 3.7+. +Unix: + python3 LexillaGen.py +Windows: + pyw LexillaGen.py diff --git a/src/lexilla/access/LexillaAccess.cxx b/src/lexilla/access/LexillaAccess.cxx new file mode 100644 index 000000000..0d77a8bab --- /dev/null +++ b/src/lexilla/access/LexillaAccess.cxx @@ -0,0 +1,285 @@ +// SciTE - Scintilla based Text Editor +/** @file LexillaAccess.cxx + ** Interface to loadable lexers. + ** Maintains a list of lexer library paths and CreateLexer functions. + ** If list changes then load all the lexer libraries and find the functions. + ** When asked to create a lexer, call each function until one succeeds. + **/ +// Copyright 2019 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <cstring> + +#include <string> +#include <string_view> +#include <vector> +#include <set> + +#if !defined(_WIN32) +#include <dlfcn.h> +#else +#include <windows.h> +#endif + +#include "ILexer.h" + +#include "Lexilla.h" + +#include "LexillaAccess.h" + +namespace { + +#if defined(_WIN32) +typedef FARPROC Function; +typedef HMODULE Module; +constexpr const char *pathSeparator = "\\"; +#else +typedef void *Function; +typedef void *Module; +constexpr const char *pathSeparator = "/"; +#endif + +/// Generic function to convert from a Function(void* or FARPROC) to a function pointer. +/// This avoids undefined and conditionally defined behaviour. +template<typename T> +T FunctionPointer(Function function) noexcept { + static_assert(sizeof(T) == sizeof(function)); + T fp {}; + memcpy(&fp, &function, sizeof(T)); + return fp; +} + +#if defined(_WIN32) + +std::wstring WideStringFromUTF8(std::string_view sv) { + const int sLength = static_cast<int>(sv.length()); + const int cchWide = ::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, nullptr, 0); + std::wstring sWide(cchWide, 0); + ::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, sWide.data(), cchWide); + return sWide; +} + +#endif + +// Turn off deprecation checks as LexillaAccess deprecates its wrapper over +// the deprecated LexerNameFromID. Thus use within LexillaAccess is intentional. +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#else +#pragma warning(disable: 4996) +#endif + +std::string directoryLoadDefault; +std::string lastLoaded; + +struct LexLibrary { + Lexilla::CreateLexerFn fnCL; + Lexilla::LexerNameFromIDFn fnLNFI; + Lexilla::GetLibraryPropertyNamesFn fnGLPN; + Lexilla::SetLibraryPropertyFn fnSLP; + std::string nameSpace; +}; +std::vector<LexLibrary> libraries; + +std::vector<std::string> lexers; +std::vector<std::string> libraryProperties; + +Function FindSymbol(Module m, const char *symbol) noexcept { +#if defined(_WIN32) + return ::GetProcAddress(m, symbol); +#else + return dlsym(m, symbol); +#endif +} + +Lexilla::CreateLexerFn pCreateLexerDefault = nullptr; + +bool NameContainsDot(std::string_view path) noexcept { + for (std::string_view::const_reverse_iterator it = path.crbegin(); + it != path.crend(); ++it) { + if (*it == '.') + return true; + if (*it == '/' || *it == '\\') + return false; + } + return false; +} + +constexpr bool HasPrefix(std::string_view s, std::string_view prefix) noexcept { + return (s.size() >= prefix.size()) && (prefix == s.substr(0, prefix.size())); +} + +} + +void Lexilla::SetDefault(CreateLexerFn pCreate) noexcept { + pCreateLexerDefault = pCreate; +} + +void Lexilla::SetDefaultDirectory(std::string_view directory) { + directoryLoadDefault = directory; +} + +bool Lexilla::Load(std::string_view sharedLibraryPaths) { + if (sharedLibraryPaths == lastLoaded) { + return !libraries.empty(); + } + + std::string_view paths = sharedLibraryPaths; + lexers.clear(); + + libraries.clear(); + while (!paths.empty()) { + const size_t separator = paths.find_first_of(';'); + std::string path(paths.substr(0, separator)); + if (separator == std::string::npos) { + paths.remove_prefix(paths.size()); + } else { + paths.remove_prefix(separator + 1); + } + if (path == ".") { + if (directoryLoadDefault.empty()) { + path = ""; + } else { + path = directoryLoadDefault; + path += pathSeparator; + } + path += LEXILLA_LIB; + } + if (!NameContainsDot(path)) { + // No '.' in name so add extension + path.append(LEXILLA_EXTENSION); + } +#if defined(_WIN32) + // Convert from UTF-8 to wide characters + std::wstring wsPath = WideStringFromUTF8(path); + Module lexillaDL = ::LoadLibraryW(wsPath.c_str()); +#else + Module lexillaDL = dlopen(path.c_str(), RTLD_LAZY); +#endif + if (lexillaDL) { + GetLexerCountFn fnLexerCount = FunctionPointer<GetLexerCountFn>( + FindSymbol(lexillaDL, LEXILLA_GETLEXERCOUNT)); + GetLexerNameFn fnLexerName = FunctionPointer<GetLexerNameFn>( + FindSymbol(lexillaDL, LEXILLA_GETLEXERNAME)); + if (fnLexerCount && fnLexerName) { + const int nLexers = fnLexerCount(); + for (int i = 0; i < nLexers; i++) { + char name[100] = ""; + fnLexerName(i, name, sizeof(name)); + lexers.push_back(name); + } + } + CreateLexerFn fnCL = FunctionPointer<CreateLexerFn>( + FindSymbol(lexillaDL, LEXILLA_CREATELEXER)); + LexerNameFromIDFn fnLNFI = FunctionPointer<LexerNameFromIDFn>( + FindSymbol(lexillaDL, LEXILLA_LEXERNAMEFROMID)); + GetLibraryPropertyNamesFn fnGLPN = FunctionPointer<GetLibraryPropertyNamesFn>( + FindSymbol(lexillaDL, LEXILLA_GETLIBRARYPROPERTYNAMES)); + SetLibraryPropertyFn fnSLP = FunctionPointer<SetLibraryPropertyFn>( + FindSymbol(lexillaDL, LEXILLA_SETLIBRARYPROPERTY)); + GetNameSpaceFn fnGNS = FunctionPointer<GetNameSpaceFn>( + FindSymbol(lexillaDL, LEXILLA_GETNAMESPACE)); + std::string nameSpace; + if (fnGNS) { + nameSpace = fnGNS(); + nameSpace += LEXILLA_NAMESPACE_SEPARATOR; + } + LexLibrary lexLib { + fnCL, + fnLNFI, + fnGLPN, + fnSLP, + nameSpace + }; + libraries.push_back(lexLib); + } + } + lastLoaded = sharedLibraryPaths; + + std::set<std::string> nameSet; + for (const LexLibrary &lexLib : libraries) { + if (lexLib.fnGLPN) { + const char *cpNames = lexLib.fnGLPN(); + if (cpNames) { + std::string_view names = cpNames; + while (!names.empty()) { + const size_t separator = names.find_first_of('\n'); + std::string name(names.substr(0, separator)); + nameSet.insert(name); + if (separator == std::string::npos) { + names.remove_prefix(names.size()); + } else { + names.remove_prefix(separator + 1); + } + } + } + } + } + // Standard Lexilla does not have any properties so can't be added to set. + libraryProperties = std::vector<std::string>(nameSet.begin(), nameSet.end()); + + return !libraries.empty(); +} + +Scintilla::ILexer5 *Lexilla::MakeLexer(std::string_view languageName) { + std::string sLanguageName(languageName); // Ensure NUL-termination + // First, try to match namespace then name suffix + for (const LexLibrary &lexLib : libraries) { + if (lexLib.fnCL && !lexLib.nameSpace.empty()) { + if (HasPrefix(languageName, lexLib.nameSpace)) { + Scintilla::ILexer5 *pLexer = lexLib.fnCL(sLanguageName.substr(lexLib.nameSpace.size()).c_str()); + if (pLexer) { + return pLexer; + } + } + } + } + // If no match with namespace, try to just match name + for (const LexLibrary &lexLib : libraries) { + if (lexLib.fnCL) { + Scintilla::ILexer5 *pLexer = lexLib.fnCL(sLanguageName.c_str()); + if (pLexer) { + return pLexer; + } + } + } + if (pCreateLexerDefault) { + return pCreateLexerDefault(sLanguageName.c_str()); + } +#if defined(LEXILLA_STATIC) + Scintilla::ILexer5 *pLexer = CreateLexer(sLanguageName.c_str()); + if (pLexer) { + return pLexer; + } +#endif + return nullptr; +} + +std::vector<std::string> Lexilla::Lexers() { + return lexers; +} + +std::string Lexilla::NameFromID(int identifier) { + for (const LexLibrary &lexLib : libraries) { + if (lexLib.fnLNFI) { + const char *name = lexLib.fnLNFI(identifier); + if (name) { + return name; + } + } + } + return std::string(); +} + +std::vector<std::string> Lexilla::LibraryProperties() { + return libraryProperties; +} + +void Lexilla::SetProperty(const char *key, const char *value) { + for (const LexLibrary &lexLib : libraries) { + if (lexLib.fnSLP) { + lexLib.fnSLP(key, value); + } + } + // Standard Lexilla does not have any properties so don't set. +} diff --git a/src/lexilla/access/LexillaAccess.h b/src/lexilla/access/LexillaAccess.h new file mode 100644 index 000000000..5979503d4 --- /dev/null +++ b/src/lexilla/access/LexillaAccess.h @@ -0,0 +1,35 @@ +// SciTE - Scintilla based Text Editor +/** @file LexillaAccess.h + ** Interface to loadable lexers. + ** This does not depend on SciTE code so can be copied out into other projects. + **/ +// Copyright 2019 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef LEXILLAACCESS_H +#define LEXILLAACCESS_H + +namespace Lexilla { + +// Directory to load default Lexilla from, commonly the directory of the application. +void SetDefaultDirectory(std::string_view directory); + +// Specify CreateLexer when statically linked so no hard dependency in LexillaAccess +// so it doesn't have to be built in two forms - static and dynamic. +void SetDefault(CreateLexerFn pCreate) noexcept; + +// sharedLibraryPaths is a ';' separated list of shared libraries to load. +// On Win32 it is treated as UTF-8 and on Unix it is passed to dlopen directly. +// Return true if any shared libraries are loaded. +bool Load(std::string_view sharedLibraryPaths); + +Scintilla::ILexer5 *MakeLexer(std::string_view languageName); + +std::vector<std::string> Lexers(); +[[deprecated]] std::string NameFromID(int identifier); +std::vector<std::string> LibraryProperties(); +void SetProperty(const char *key, const char *value); + +} + +#endif diff --git a/src/lexilla/access/README b/src/lexilla/access/README new file mode 100644 index 000000000..97e28e599 --- /dev/null +++ b/src/lexilla/access/README @@ -0,0 +1,9 @@ +README for access directory. + +LexillaAccess is a module that simplifies using multiple libraries that follow the Lexilla protocol. + +It can be compiled into a Lexilla client application. + +Applications with complex needs can copy the code and customise it to meet their requirements. + +This module is not meant to be compiled into Lexilla. diff --git a/src/lexilla/bin/empty.txt b/src/lexilla/bin/empty.txt new file mode 100644 index 000000000..66183855a --- /dev/null +++ b/src/lexilla/bin/empty.txt @@ -0,0 +1 @@ +This empty files ensures that the directory is created. \ No newline at end of file diff --git a/src/lexilla/cppcheck.suppress b/src/lexilla/cppcheck.suppress new file mode 100644 index 000000000..5fbab62e6 --- /dev/null +++ b/src/lexilla/cppcheck.suppress @@ -0,0 +1,215 @@ +// File to suppress cppcheck warnings for files that will not be fixed. +// Does not suppress warnings where an additional occurrence of the warning may be of interest. +// Configured for cppcheck 2.12 + +// Coding style is to use assignments in constructor when there are many +// members to initialize or the initialization is complex or has comments. +useInitializationList + +// These may be interesting but its not clear without examining each instance closely +// Would have to ensure that any_of/all_of has same early/late exits as current code and +// produces same result on empty collections +useStlAlgorithm + +// Common for lexer object destructors +missingOverride + +// Some non-explicit constructors are used for conversions or are private to lexers +noExplicitConstructor + +// The performance cost of by-value passing is often small and using a reference decreases +// code legibility. +passedByValue + +// cppcheck 2.11 can't find system headers on Win32. +missingIncludeSystem + +// Passing temporary string into hidden object creator functions: they do not hold the argument +danglingTemporaryLifetime:lexilla/access/LexillaAccess.cxx +returnDanglingLifetime:lexilla/access/LexillaAccess.cxx + +// cppcheck seems to believe that unique_ptr<char *[]>::get returns void* instead of char** +arithOperationsOnVoidPointer:lexilla/lexlib/WordList.cxx + +// cppcheck 2.11 limits checking of complex functions unless --check-level=exhaustive but that +// only finds one false issue in LexRuby +checkLevelNormal:lexilla/lexers/LexBash.cxx +checkLevelNormal:lexilla/lexers/LexCPP.cxx +checkLevelNormal:lexilla/lexers/LexHTML.cxx +checkLevelNormal:lexilla/lexers/LexPerl.cxx +checkLevelNormal:lexilla/lexers/LexRuby.cxx + +// Physically but not logically const. +constVariablePointer:lexilla/examples/CheckLexilla/CheckLexilla.c + +// Suppress most lexer warnings since the lexers are maintained by others +redundantCondition:lexilla/lexers/LexA68k.cxx +constParameterReference:lexilla/lexers/LexAbaqus.cxx +constParameterReference:lexilla/lexers/LexAda.cxx +constParameterReference:lexilla/lexers/LexAsciidoc.cxx +constParameterCallback:lexilla/lexers/LexAsn1.cxx +knownConditionTrueFalse:lexilla/lexers/LexAU3.cxx +shadowVariable:lexilla/lexers/LexAU3.cxx +constParameterReference:lexilla/lexers/LexBaan.cxx +unreadVariable:lexilla/lexers/LexBaan.cxx +variableScope:lexilla/lexers/LexBaan.cxx +constParameterPointer:lexilla/lexers/LexBaan.cxx +constParameterReference:lexilla/lexers/LexBash.cxx +knownConditionTrueFalse:lexilla/lexers/LexBash.cxx +variableScope:lexilla/lexers/LexBash.cxx +constVariable:lexilla/lexers/LexBasic.cxx +constParameterReference:lexilla/lexers/LexCLW.cxx +knownConditionTrueFalse:lexilla/lexers/LexCLW.cxx +variableScope:lexilla/lexers/LexCmake.cxx +knownConditionTrueFalse:lexilla/lexers/LexCmake.cxx +constParameterReference:lexilla/lexers/LexCmake.cxx +constParameterReference:lexilla/lexers/LexCOBOL.cxx +constParameterReference:lexilla/lexers/LexCoffeeScript.cxx +constParameterPointer:lexilla/lexers/LexCoffeeScript.cxx +knownConditionTrueFalse:lexilla/lexers/LexCoffeeScript.cxx +constVariableReference:lexilla/lexers/LexConf.cxx +constParameterReference:lexilla/lexers/LexCPP.cxx +variableScope:lexilla/lexers/LexCSS.cxx +knownConditionTrueFalse:lexilla/lexers/LexDataflex.cxx +constParameterReference:lexilla/lexers/LexDataflex.cxx +variableScope:lexilla/lexers/LexDataflex.cxx +knownConditionTrueFalse:lexilla/lexers/LexECL.cxx +variableScope:lexilla/lexers/LexECL.cxx +constParameter:lexilla/lexers/LexEDIFACT.cxx +constParameterPointer:lexilla/lexers/LexEDIFACT.cxx +knownConditionTrueFalse:lexilla/lexers/LexEiffel.cxx +variableScope:lexilla/lexers/LexErlang.cxx +knownConditionTrueFalse:lexilla/lexers/LexEScript.cxx +constParameter:lexilla/lexers/LexFortran.cxx +constParameterReference:lexilla/lexers/LexFortran.cxx +redundantContinue:lexilla/lexers/LexFortran.cxx +knownConditionTrueFalse:lexilla/lexers/LexFSharp.cxx +constParameterReference:lexilla/lexers/LexGAP.cxx +constParameterReference:lexilla/lexers/LexGDScript.cxx +variableScope:lexilla/lexers/LexGui4Cli.cxx +constParameterReference:lexilla/lexers/LexHaskell.cxx +constParameterReference:lexilla/lexers/LexHex.cxx +knownConditionTrueFalse:lexilla/lexers/LexHex.cxx +constVariable:lexilla/lexers/LexHollywood.cxx +variableScope:lexilla/lexers/LexInno.cxx +constVariableReference:lexilla/lexers/LexInno.cxx +constParameterReference:lexilla/lexers/LexJSON.cxx +constParameterPointer:lexilla/lexers/LexJulia.cxx +constParameterReference:lexilla/lexers/LexJulia.cxx +knownConditionTrueFalse:lexilla/lexers/LexJulia.cxx +unreadVariable:lexilla/lexers/LexJulia.cxx +variableScope:lexilla/lexers/LexJulia.cxx +variableScope:lexilla/lexers/LexLaTeX.cxx +constParameterReference:lexilla/lexers/LexLaTeX.cxx +constParameterPointer:lexilla/lexers/LexMagik.cxx +constParameterReference:lexilla/lexers/LexMagik.cxx +constParameterReference:lexilla/lexers/LexMarkdown.cxx +constParameterPointer:lexilla/lexers/LexMatlab.cxx +constParameterReference:lexilla/lexers/LexMatlab.cxx +unreadVariable:lexilla/lexers/LexMatlab.cxx +variableScope:lexilla/lexers/LexMatlab.cxx +variableScope:lexilla/lexers/LexMetapost.cxx +constParameterReference:lexilla/lexers/LexModula.cxx +variableScope:lexilla/lexers/LexModula.cxx +constParameterReference:lexilla/lexers/LexMPT.cxx +variableScope:lexilla/lexers/LexMSSQL.cxx +shadowArgument:lexilla/lexers/LexMySQL.cxx +constParameterReference:lexilla/lexers/LexNim.cxx +constParameterReference:lexilla/lexers/LexNimrod.cxx +knownConditionTrueFalse:lexilla/lexers/LexNimrod.cxx +variableScope:lexilla/lexers/LexNimrod.cxx +variableScope:lexilla/lexers/LexNsis.cxx +constParameterReference:lexilla/lexers/LexNsis.cxx +knownConditionTrueFalse:lexilla/lexers/LexNsis.cxx +variableScope:lexilla/lexers/LexOpal.cxx +constParameterReference:lexilla/lexers/LexOpal.cxx +knownConditionTrueFalse:lexilla/lexers/LexOpal.cxx +constParameterReference:lexilla/lexers/LexOScript.cxx +constParameterReference:lexilla/lexers/LexPascal.cxx +variableScope:lexilla/lexers/LexPB.cxx +constParameterReference:lexilla/lexers/LexPerl.cxx +constVariableReference:lexilla/lexers/LexPerl.cxx +knownConditionTrueFalse:lexilla/lexers/LexPerl.cxx +constParameterReference:lexilla/lexers/LexPLM.cxx +constParameterReference:lexilla/lexers/LexPO.cxx +constParameterReference:lexilla/lexers/LexPython.cxx +shadowVariable:lexilla/lexers/LexPowerPro.cxx +knownConditionTrueFalse:lexilla/lexers/LexPowerPro.cxx +variableScope:lexilla/lexers/LexProgress.cxx +constParameterReference:lexilla/lexers/LexProgress.cxx +constParameterReference:lexilla/lexers/LexRaku.cxx +variableScope:lexilla/lexers/LexRaku.cxx +redundantInitialization:lexilla/lexers/LexRegistry.cxx +constParameterReference:lexilla/lexers/LexRuby.cxx +constParameterReference:lexilla/lexers/LexRust.cxx +knownConditionTrueFalse:lexilla/lexers/LexScriptol.cxx +variableScope:lexilla/lexers/LexSpecman.cxx +unreadVariable:lexilla/lexers/LexSpice.cxx +constParameterReference:lexilla/lexers/LexSpice.cxx +constParameterReference:lexilla/lexers/LexSTTXT.cxx +constParameterReference:lexilla/lexers/LexTACL.cxx +knownConditionTrueFalse:lexilla/lexers/LexTACL.cxx +clarifyCalculation:lexilla/lexers/LexTADS3.cxx +constParameterReference:lexilla/lexers/LexTADS3.cxx +constParameterReference:lexilla/lexers/LexTAL.cxx +constVariableReference:lexilla/lexers/LexTCL.cxx +invalidscanf:lexilla/lexers/LexTCMD.cxx +constParameterReference:lexilla/lexers/LexTeX.cxx +variableScope:lexilla/lexers/LexTeX.cxx +knownConditionTrueFalse:lexilla/lexers/LexVB.cxx +constParameterReference:lexilla/lexers/LexVerilog.cxx +variableScope:lexilla/lexers/LexVerilog.cxx +badBitmaskCheck:lexilla/lexers/LexVerilog.cxx +uselessCallsSubstr:lexilla/lexers/LexVerilog.cxx +constParameterReference:lexilla/lexers/LexVHDL.cxx +constVariable:lexilla/lexers/LexVHDL.cxx +shadowVariable:lexilla/lexers/LexVHDL.cxx +unreadVariable:lexilla/lexers/LexVHDL.cxx +variableScope:lexilla/lexers/LexVHDL.cxx +unreadVariable:lexilla/lexers/LexVisualProlog.cxx +variableScope:lexilla/lexers/LexVisualProlog.cxx +shiftTooManyBitsSigned:lexilla/lexers/LexVisualProlog.cxx +iterateByValue:lexilla/lexers/LexVisualProlog.cxx +unreadVariable:lexilla/lexers/LexX12.cxx +constVariableReference:lexilla/lexers/LexX12.cxx +constParameterPointer:lexilla/lexers/LexX12.cxx +uselessCallsSubstr:lexilla/lexers/LexX12.cxx +constParameterReference:lexilla/lexers/LexYAML.cxx +constParameterPointer:lexilla/lexers/LexYAML.cxx +knownConditionTrueFalse:lexilla/lexers/LexYAML.cxx + +// These are due to Accessor::IndentAmount not declaring the callback as taking a const. +// Changing this could cause problems for downstream projects. +constParameterCallback:lexilla/lexers/LexEiffel.cxx +constParameterCallback:lexilla/lexers/LexGDScript.cxx +constParameterCallback:lexilla/lexers/LexPython.cxx +constParameterCallback:lexilla/lexers/LexScriptol.cxx +constParameterCallback:lexilla/lexers/LexVB.cxx + +constVariableReference:lexilla/lexers/LexBibTeX.cxx +constVariableReference:lexilla/lexers/LexCSS.cxx +constVariableReference:lexilla/lexers/LexCrontab.cxx +constVariableReference:lexilla/lexers/LexGui4Cli.cxx +constVariableReference:lexilla/lexers/LexMetapost.cxx +constVariableReference:lexilla/lexers/LexOpal.cxx + +// Suppress everything in test example files +*:lexilla/test/examples/* + +// Suppress everything in catch.hpp as won't be changing +*:lexilla/test/unit/catch.hpp +// cppcheck gives up inside catch.hpp +*:lexilla/test/unit/UnitTester.cxx +*:lexilla/test/unit/unitTest.cxx + +// Tests often test things that are always true +knownConditionTrueFalse:lexilla/test/unit/testCharacterSet.cxx + +// cppcheck fails REQUIRE from Catch +comparisonOfFuncReturningBoolError:lexilla/test/unit/*.cxx + +// cppcheck fails SECTION from Catch +syntaxError:lexilla/test/unit/*.cxx + +// argv has a standardised type +constParameter:lexilla/examples/CheckLexilla/CheckLexilla.c diff --git a/src/lexilla/delbin.bat b/src/lexilla/delbin.bat new file mode 100644 index 000000000..05e953377 --- /dev/null +++ b/src/lexilla/delbin.bat @@ -0,0 +1 @@ +@del /S /Q *.a *.aps *.bsc *.dll *.dsw *.exe *.idb *.ilc *.ild *.ilf *.ilk *.ils *.lib *.map *.ncb *.obj *.o *.opt *.ipdb *.pdb *.plg *.res *.sbr *.tds *.exp *.tlog *.lastbuildstate >NUL: diff --git a/src/lexilla/doc/Lexilla.html b/src/lexilla/doc/Lexilla.html new file mode 100644 index 000000000..d2d2a0ff9 --- /dev/null +++ b/src/lexilla/doc/Lexilla.html @@ -0,0 +1,161 @@ +<?xml version="1.0"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta name="generator" content="HTML Tidy, see www.w3.org" /> + <meta name="generator" content="SciTE" /> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> + <meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" /> + <meta name="Description" + content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." /> + <meta name="Date.Modified" content="20240821" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <style type="text/css"> + .logo { + background: url(https://www.scintilla.org/LexillaLogo.png) no-repeat; + background-image: image-set( + url(https://www.scintilla.org/LexillaLogo.png) 1x, + url(https://www.scintilla.org/LexillaLogo2x.png) 2x ); + height:150px; + } + #versionlist { + margin: 0; + padding: .5em; + list-style-type: none; + color: #FFCC99; + background: #000000; + } + #versionlist li { + margin-bottom: .5em; + } + #menu { + margin: 0; + padding: .5em 0; + list-style-type: none; + font-size: larger; + background: #CCCCCC; + } + #menu li { + margin: 0; + padding: 0 .5em; + display: inline; + } + </style> + <script type="text/javascript"> + function IsRemote() { + var loc = '' + window.location; + return (loc.indexOf('http:')) != -1 || (loc.indexOf('https:') != -1); + } + </script> + <title> + Lexilla + + + + + + + + + + +
+ + A library of language lexers for use with Scintilla + + Release version 5.4.0
+ Site last modified August 21 2024
+
+   +
+ + + + +
+
    +
  • Version 5.4.0 adds a TOML lexer.
  • +
  • Version 5.3.3 improves HTML, JavaScript, Lua, PHP, and XML.
  • +
  • Version 5.3.2 improves COBOL, HTML, Lua, Ruby, and Rust.
  • +
  • Version 5.3.1 improves Assembler, Bash, Batch, JavaScript, Python, and Ruby.
  • +
  • Version 5.3.0 improves Bash, HTML, and Lua.
  • +
+ + +

+ Lexilla is a free library of language + lexers that can be used with the Scintilla + editing component. + It comes with complete source code and a license that + permits use in any free project or commercial product. +

+

+ Originally, this functionality was incorporated inside Scintilla. + It has been extracted as a separate project to make it easier for contributors to work on + support for new languages and to fix bugs in existing lexers. + It also defines a protocol where projects can implement their own lexers and distribute + them as they wish. +

+

+ Current development requires a recent C++ compiler that supports C++17. + The testing framework uses some C++20 features but the basic library only uses C++17. +

+

+ Lexilla is currently available for Intel Win32, macOS, and Linux compatible operating + systems. It has been run on Windows 10, macOS 10.13+, and on Ubuntu 20.04 but is likely + to run on earlier systems as it has no GUI functionality. +

+

+ You can download Lexilla. +

+

+ The source code can be downloaded via Git at GitHub + Lexilla project page.
+ git clone https://github.com/ScintillaOrg/lexilla +

+

Current repository status:
+
+
+ +

+

+ Related sites. +

+

+ Bugs and other issues. +

+

+ History and contribution credits. +

+

+ Questions and comments about Lexilla should be directed to the + scintilla-interest + mailing list, + which is for discussion of Scintilla and related projects, their bugs and future features. + This is a low traffic list, averaging less than 20 messages per week. + To avoid spam, only list members can write to the list. + New versions of Lexilla are announced on scintilla-interest. +
+

+ + + diff --git a/src/lexilla/doc/LexillaDoc.html b/src/lexilla/doc/LexillaDoc.html new file mode 100644 index 000000000..be1b972fe --- /dev/null +++ b/src/lexilla/doc/LexillaDoc.html @@ -0,0 +1,254 @@ + + + + + + + + + + Lexilla Documentation + + + + + + + + + + + +
Lexilla iconLexilla
+ +

Lexilla Documentation

+ +

Last edited 21 April 2021 NH

+ +

Introduction

+ +

Lexilla is a library containing lexers for use with Scintilla. It can be either a static library + that is linked into an application or a shared library that is loaded at runtime.

+ +

Lexilla does not interact with the display so there is no need to compile it for a + particular GUI toolkit. Therefore there can be a common library shared by applications using + different GUI toolkits. In some circumstances there may need to be both 32-bit and 64-bit versions + on one system to match different applications.

+ +

Different extensions are commonly used for shared libraries: .so on Linux, .dylib on macOS, and .DLL on Windows. +

+ +

The Lexilla protocol

+ +

A set of functions is defined by Lexilla for use by applications. Libraries that provide these functions + can be used as a replacement for Lexilla or to add new lexers beyond those provided by Lexilla.

+ +

The Lexilla protocol is a superset of the external lexer protocol and defines these functions that may be exported from a shared library:
+ int GetLexerCount()
+ void GetLexerName(unsigned int index, char *name, int buflength)
+ LexerFactoryFunction GetLexerFactory(unsigned int index)
+ ILexer5 *CreateLexer(const char *name)
+ const char *LexerNameFromID(int identifier)
+ const char *GetLibraryPropertyNames()
+ void SetLibraryProperty(const char *key, const char *value)
+ const char *GetNameSpace() +

+ +

ILexer5 is defined by Scintilla in include/ILexer.h as the interface provided by lexers which is called by Scintilla. + Many clients do not actually need to call methods on ILexer5 - they just take the return from CreateLexer and plug it + straight into Scintilla so it can be treated as a machine pointer (void *). +

+ +

LexerFactoryFunction is defined as a function that takes no arguments and returns an ILexer5 *: + ILexer5 *(*LexerFactoryFunction)() but this can be ignored by most client code. +

+ +

The Lexilla protocol is a superset of the earlier external lexer protocol that defined the first 3 functions + (GetLexerCount, GetLexerName, GetLexerFactory) + so Lexilla can be loaded by applications that support that protocol. + GetLexerFactory will rarely be used now as it is easier to call CreateLexer. +

+ +

CreateLexer is the main call that will create a lexer for a particular language. The returned lexer can then be + set as the current lexer in Scintilla by calling + SCI_SETILEXER.

+ +

LexerNameFromID is an optional function that returns the name for a lexer identifier. + LexerNameFromID(SCLEX_CPP) → "cpp". + This is a temporary affordance to make it easier to convert applications to using Lexilla. + Applications should move to using lexer names instead of IDs. + This function is deprecated, showing warnings with some compilers, and will be removed in a future version of Lexilla.

+ +

SetLibraryProperty and GetLibraryPropertyNames + are optional functions that can be + defined if a library requires initialisation before calling other methods. + For example, a lexer library that reads language definitions from XML files may require that the + directory containing these files be set before a call to CreateLexer. + SetLibraryProperty("definitions.directory", "/usr/share/xeditor/language-definitions") + If a library implements SetLibraryProperty then it may also provide a set of valid property names with + GetLibraryPropertyNames that can then be used by the application to define configuration file property + names or user interface elements for options dialogs.

+ +

GetNameSpace is an optional function that returns a namespace string + that can be used to disambiguate lexers with the same name from different providers. + If Lexilla and XMLLexers both provide a "cpp" lexer than a request for "cpp" may be satisfied by either but "xmllexers.cpp" + unambiguously refers to the "cpp" lexer from XMLLexers.

+ +

Building Lexilla

+ +

Before using Lexilla it must be built or downloaded.

+

Lexilla requires some headers from Scintilla to build and expects a directory named + "scintilla" containing a copy of Scintilla 5+ to be a peer of the Lexilla top level + directory conventionally called "lexilla".

+ +
To build Lexilla, in the lexilla/src directory, run make (for gcc or clang)
+
make
+
or nmake for MSVC
+
nmake -f lexilla.mak
+
+ +
After building Lexilla, its test suite can be run with make/nmake in the lexilla/test directory. For gcc or clang
+
make test
+ or for MSVC
+
nmake -f testlexers.mak test
+
Each test case should show "Lexing ..." and errors will display a diagnostic, commonly showing + a difference between the actual and expected result:
+ C:\u\hg\lexilla\test\examples\python\x.py:1: is different +
+ +

There are also RunTest.sh / RunTest.bat scripts in the scripts directory to build Lexilla and then build and run the tests. + These both use gcc/clang, not MSVC.

+ +

There are Microsoft Visual C++ and Xcode projects that can be used to build Lexilla. + For Visual C++: src/Lexilla.vcxproj. For Xcode: src/Lexilla/Lexilla.xcodeproj. + There is also test/TestLexers.vcxproj to build the tests with Visual C++.

+ +

Using Lexilla

+ +

Definitions for using Lexilla from C and C++ are included in lexilla/include/Lexilla.h. + For C++, scintilla/include/ILexer.h should be included before Lexilla.h as the + ILexer5 type is used. + For C, ILexer.h should not be included as C does not understand it and from C, + void* is used instead of ILexer5*. +

+ +

For many applications the main Lexilla operations are loading the Lexilla library, creating a + lexer and using that lexer in Scintilla. + Applications need to define the location (or locations) they expect + to find Lexilla or libraries that support the Lexilla protocol. + They also need to define how they request particular lexers, perhaps with a mapping from + file extensions to lexer names.

+ +

From C - CheckLexilla

+ +

An example C program for accessing Lexilla is provided in lexilla/examples/CheckLexilla. + Build with make and run with make check. +

+ +

From C++ - LexillaAccess

+ +

A C++ module, LexillaAccess.cxx / LexillaAccess.h is provided in lexilla/access. + This can either be compiled into the application when it is sufficient + or the source code can be copied into the application and customized when the application has additional requirements + (such as checking code signatures). + SciTE uses LexillaAccess.

+ +

LexillaAccess supports loading multiple shared libraries implementing the Lexilla protocol at one time.

+ +

From Qt

+ +

For Qt, use either LexillaAccess from above or Qt's QLibrary class. With 'Call' defined to call Scintilla APIs.
+ +#if _WIN32
+    typedef void *(__stdcall *CreateLexerFn)(const char *name);
+#else
+    typedef void *(*CreateLexerFn)(const char *name);
+#endif
+    QFunctionPointer fn = QLibrary::resolve("lexilla", "CreateLexer");
+    void *lexCpp = ((CreateLexerFn)fn)("cpp");
+    Call(SCI_SETILEXER, 0, (sptr_t)(void *)lexCpp);
+

+ +

Applications may discover the set of lexers provided by a library by first calling + GetLexerCount to find the number of lexers implemented in the library then looping over calling + GetLexerName with integers 0 to GetLexerCount()-1.

+ +

Applications may set properties on a library by calling SetLibraryProperty if provided. + This may be needed for initialisation so should before calling GetLexerCount or CreateLexer. + A set of property names may be available from GetLibraryPropertyNames if provided. + It returns a string pointer where the string contains a list of property names separated by '\n'. + It is up to applications to define how properties are defined and persisted in its user interface + and configuration files.

+ +

Modifying or adding lexers

+ +

Lexilla can be modified or a new library created that can be used to replace or augment Lexilla.

+ +

Lexer libraries that provide the same functions as Lexilla may provide lexers for use by Scintilla, + augmenting or replacing those provided by Lexilla. + To allow initialisation of lexer libraries, a SetLibraryProperty(const char *key, const char *value) + may optionally be implemented. For example, a lexer library that uses XML based lexer definitions may + be provided with a directory to search for such definitions. + Lexer libraries should ignore any properties that they do not understand. + The set of properties supported by a lexer library is specified as a '\n' separated list of property names by + an optional const char *GetLibraryPropertyNames() function. +

+ +

Lexilla and its contained lexers can be tested with the TestLexers program in lexilla/test. + Read lexilla/test/README for information on building and using TestLexers.

+ +

An example of a simple lexer housed in a shared library that is compatible with the + Lexilla protocol can be found in lexilla/examples/SimpleLexer. It is implemented in C++. + Build with make and check by running CheckLexilla against it with + make check. +

+ + + + diff --git a/src/lexilla/doc/LexillaDownload.html b/src/lexilla/doc/LexillaDownload.html new file mode 100644 index 000000000..5fd332363 --- /dev/null +++ b/src/lexilla/doc/LexillaDownload.html @@ -0,0 +1,71 @@ + + + + + + + + + + Download Lexilla + + + + + + + + +
+ Scintilla icon + + Download + Lexilla +
+ + + + +
+ + Windows   + + GTK/Linux   + +
+

+ Download. +

+

+ The license for using Lexilla is similar to that of Python + containing very few restrictions. +

+

+ Release 5.4.0 +

+

+ Source Code +

+ The source code package contains all of the source code for Lexilla but no binary + executable code and is available in +
    +
  • zip format (1.3M) commonly used on Windows
  • +
  • tgz format (0.9M) commonly used on Linux and compatible operating systems
  • +
+ Instructions for building on both Windows and Linux are included in the readme file. +

+ Windows Executable Code +

+ There is no download available containing only the Lexilla DLL. + However, it is included in the SciTE + executable full download as Lexilla.DLL. +

+ SciTE is a good demonstration of Lexilla. +

+

+ Previous versions can be downloaded from the history + page. +

+ + diff --git a/src/lexilla/doc/LexillaHistory.html b/src/lexilla/doc/LexillaHistory.html new file mode 100644 index 000000000..a850dc8e3 --- /dev/null +++ b/src/lexilla/doc/LexillaHistory.html @@ -0,0 +1,14158 @@ + + + + + + + + + + Lexilla + + + + + + + + + +
+ Scintilla icon + + Lexilla +
+

History of Lexilla

+

+ Lexilla was originally code that was part of the Scintilla project. + Thus it shares much of the history and contributors of Scintilla before it was extracted as its own project. +

+

Contributors

+

+ Thanks to all the people that have contributed patches, bug reports and suggestions. +

+

+ Source code and documentation have been contributed by +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Atsuo IshimotoMark HammondFrancois Le CoguiecDale Nagata
Ralf ReinhardtPhilippe LhosteAndrew McKinlayStephan R. A. Deibel
Hans EckardtVassili BourdoMaksim LinRobin Dunn
John EhresmanSteffen GoeldnerDeepak S.DevelopMentor
Yann GaillardAubin PaulJason DiamondAhmad Baitalmal
Paul WinwoodMaxim BaranovRagnar HøjlandChristian Obrecht
Andreas NeukoetterAdam GatesSteve LhommeFerdinand Prantl
Jan DriesMarkus GritschTahir KaracaAhmad Zawawi
Laurent le TynevezWalter BraeuAshley CambrellGarrett Serack
Holger SchmidtActiveStateJames LarcombeAlexey Yutkin
Jan HercekRichard PeclEdward K. ReamValery Kondakoff
Smári McCarthyClemens WyssSimon SteeleSerge A. Baranov
Xavier NodetWilly DevauxDavid ClainBrendon Yenson
Vamsi PotluruPraveen AmbekarAlan KnowlesKengo Jinno
Valentin ValchevMarcos E. WurziusMartin AldersonRobert Gustavsson
José FonsecaHolger KiemesFrancis IrvingScott Kirkwood
Brian QuinlanUbiMichael R. DuerigDeepak T
Don Paul BeletskyGerhard KalabOlivier DagenaisJosh Wingstrom
Bruce DodsonSergey KoshcheyevChuan-jian ShenShane Caraveo
Alexander ScripnikRyan ChristiansonMartin SteffensenJakub Vrána
The Black HorusBernd KreussThomas LauerMike Lansdaal
Yukihiro NakaiJochen TuchtGreg SmithSteve Schoettler
Mauritius ThinnesDarren SchroederPedro GuerreiroSteven te Brinke
Dan PetittBiswapesh ChattopadhyayKein-Hong ManPatrizio Bekerle
Nigel HathawayHrishikesh DesaiSergey PuljajevMathias Rauen
Angelo MandatoDenis SureauKaspar SchiessChristoph Hösler
João Paulo F FariasRon SchofieldStefan WosnikMarius Gheorghe
Naba KumarSean O'DellStefanos TogoulidisHans Hagen
Jim CapeRoland WalterBrian MosherNicholas Nemtsev
Roy WoodPeter-Henry ManderRobert BoucherChristoph Dalitz
April WhiteS. UmarTrent MickFilip Yaghob
Avi YegudinVivi OrunitiaManfred BeckerDimitris Keletsekis
YuigaDavide ScolaJason BoggsReinhold Niesner
Jos van der ZandePescumaPavol BosikJohannes Schmid
Blair McGlashanMikael HultgrenFlorian BalmerHadar Raz
Herr PfarrerBen KeyGene BarryNiki Spahiev
Carsten SperberPhil ReidIago RubioRégis Vaquette
Massimo CoràElias PschernigChris JonesJosiah Reynolds
Robert Roessler rftp.comSteve DonovanJan Martin PettersenSergey Philippov
BorujoaMichael OwensFranck MarciaMassimo Maria Ghisalberti
Frank WunderlichJosepmaria RocaTobias EngvallSuzumizaki Kimitaka
Michael CartmellPascal HurniAndreRandy Butler
Georg RitterMichael GoffioulBen HarperAdam Strzelecki
Kamen StanevSteve MenardOliver YeohEric Promislow
Joseph GalbraithJeffrey RenArmel AsselinJim Pattee
Friedrich VedderSebastian PippingAndre ArpinStanislav Maslovski
Martin StoneFabien ProriolmimirNicola Civran
SnowMitchell ForalPieter HoltzhausenWaldemar Augustyn
Jason HaslamSebastian SteinlechnerChris RickardRob McMullen
Stefan SchwendelerCristian AdamNicolas ChachereauIstvan Szollosi
Xie RenhuiEnrico TrögerTodd WhitemanYuval Papish
instantonSergio LucatoVladVRODmitry Maslov
chupakabraJuan Carlos Arevalo BaezaNick TreleavenStephen Stagg
Jean-Paul IribarrenTim GerundtSam HarwellBoris
Jason OsterGertjan KloostermanalexbodnSergiu Dotenco
Anders KarlssonozlooperMarko NjezicEugen Bitter
Christoph BaumannChristopher BeanSergey KishchenkoKai Liu
Andreas RumpfJames MoffattYuzhou XinNic Jansma
Evan JonesMike LischkeEric KiddmaXmo
David SeverwrightJon StraitOliver KiddleEtienne Girondel
Haimag RenAndrey MoskalyovXaviToby Inkster
Eric ForgeotColomban WendlingNeoJordan Russell
Farshid LashkariSam RawlinsMichael MullinCarlos SS
vimMartial DemolinsTino WeinkaufJérôme Laforge
Udo LechnerMarco FaldaDariusz KnocińskiBen Fisher
Don GobinJohn YeungAdobeElizabeth A. Irizarry
Mike SchroederMorten MacFlyJaime GimenoThomas Linder Puls
Artyom ZuikovGerritOccam's RazorBen Bluemel
David WolfendaleChris AngelicoMarat DukhanStefan Weil
Rex ConnRoss McKayBruno BarbieriGordon Smith
dimitarSébastien GranjouxzenikoJames Ribe
Markus NißlMartin PanterMark YenPhilippe Elsass
Dimitar ZhekovFan YangDenis Shelomovskijdarmar
John VellaChinh NguyenSakshi VermaJoel B. Mohler
IsiledhelVidya WasiG. HuByron Hawkins
AlphaJohn DonoghuekudahIgor Shaula
Pavel BulochkinYosef Or BoczkoBrian GriffinÖzgür Emir
NeomiOmegaPhilSiegeLordErik
TJFMark RobinsonThomas Martitzfelix
Christian WaltherEbbenRobert GiesekeMike M
nkmathewAndreas TscharnerLee Wilmottjohnsonj
VicenteNick GravgaardIan GoldbyHolger Stenger
danselmiMat BerchtoldMichael StaszewskiBaurzhan Muftakhidinov
Erik AngelinYusuf Ramazan KaragözMarkus HeidelbergJoe Mueller
Mika AttilaJoMazMMarkus MoserStefan Küng
Jiří TechetJonathan HuntSerg StetsukJordan Jueckstock
Yury DubinskySam HocevarLuyomiMatt Gilarde
Mark CJohannes SasongkofstirlitzRobin Haberkorn
Pavel SountsovDirk LorenzenKasper B. GraversenChris Mayo
Van de BuggerTse Kit YamSmartShare SystemsMorten Brørup
Alexey DenisovJustin DaileyoirfeodentA-R-C-A
Roberto RossiKenny LiuIain Clarkedesto
John FlatnessThorsten KaniBernhard M. WiedemannBaldur Karlsson
Martin KleusbergJannickZufu LiuSimon Sobisch
Georger AraújoTobias KühneDimitar RadevLiang Bai
Gunter KönigsmannNicholai BenalalUnifaceRaghda Morsy
Giuseppe CorbelliAndreas RönnquistHenrik HankLuke Rasmussen
PhilippmaboroshinGokul KrishnanJohn Horigan
jj5Jad AltahanAndrea RicchiJuarez Rudsatz
Wil van AntwerpenHodong KimMichael ConradDejan Budimir
Andreas FalkenhahnMark ReayDavid ShumanMcLoo
Shmuel ZeigermanChris GrahamHugues LarrivePrakash Sahni
Michel Sauvarduhf7gnombatDerek Brown
Robert Di PardoriQQYX HaoBertrand Lacoste
Ivan UstûžaninRainer Kottenhofffeitoivsl7
Michael HeathAntonio CebriánDavid Yu YangArkadiusz Michalski
Red_McdbdevAndrey SmolyakovKnut Leimbert
German AizekTsuyoshi MiyakeMartin SchäferRainRat
+

Releases

+

+ Release 5.4.0 +

+
    +
  • + Released 21 August 2024. +
  • +
  • + Inside Lexilla, LexerModule instances are now const. + This will require changes to applications that modify Lexilla.cxx, which + may be done to add custom lexers. +
  • +
  • + Lexer added for TOML "toml". +
  • +
  • + Bash: Handle backslash in heredoc delimiter. + Issue #257. +
  • +
  • + Progress: Fix lexing of nested comments. + Pull request #258. +
  • +
  • + Force lower-casing of case-insensitive keyword lists so keywords match in some lexers. + Issue #259. +
  • +
+

+ Release 5.3.3 +

+
    +
  • + Released 22 July 2024. +
  • +
  • + ASP: Control whether ASP is enabled for XML and HTML with + lexer.xml.allow.asp and lexer.html.allow.asp. + Issue #252. +
  • +
  • + JavaScript: Recognize regular expressions at start or after '>' in JavaScript when lexer is cpp, + hypertext, or xml. + Issue #250, + Bug #918. +
  • +
  • + JavaScript: Recognize initial #! 'shebang' line as a comment in standalone files. + Issue #253. +
  • +
  • + Lua: Fix non-ASCII identifiers joined with '.' or ':'. + Issue #242. +
  • +
  • + Lua: Fix folding for multi-line SCE_LUA_LITERALSTRING and SCE_LUA_COMMENT + when performed incrementally. + Issue #247. +
  • +
  • + PHP: Control whether PHP is enabled for XML and HTML with + lexer.xml.allow.php and lexer.html.allow.php. + Issue #252. +
  • +
+

+ Release 5.3.2 +

+
    +
  • + Released 23 April 2024. +
  • +
  • + COBOL: Stop string literal continuing over line end. + Issue #229. +
  • +
  • + COBOL: Stop doc comment assigning different styles to \r and \n at line end. + Issue #229. +
  • +
  • + COBOL: Recognize keywords that start with 'V'. + Issue #230. +
  • +
  • + COBOL: Recognize comments after tag or that start with '/'. + Issue #231. +
  • +
  • + HTML: Implement substyles for tags, attributes, and identifiers + SCE_H_TAG, SCE_H_ATTRIBUTE, SCE_HJ_WORD, SCE_HJA_WORD, SCE_HB_WORD, SCE_HP_WORD, SCE_HPHP_WORD. +
  • +
  • + HTML: Implement context-sensitive attributes. "tag.attribute" matches "attribute" only inside "tag". +
  • +
  • + HTML: Match standard handling of comments. + Issue #232. +
  • +
  • + Lua: Implement substyles for identifiers SCE_LUA_IDENTIFIER. +
  • +
  • + Ruby: Allow non-ASCII here-doc delimiters. + Issue #234. +
  • +
  • + Ruby: Allow modifier if, unless, while and until after heredoc delimiter. + Issue #236. +
  • +
  • + Rust: Recognize raw identifiers. + Issue #239, + Pull request #240. +
  • +
+

+ Release 5.3.1 +

+
    +
  • + Released 5 March 2024. +
  • +
  • + Assembler: After comments, treat \r\n line ends the same as \n. This makes testing easier. +
  • +
  • + Bash: Fix folding when line changed to/from comment and previous line is comment. + Issue #224. +
  • +
  • + Batch: Fix handling ':' next to keywords. + Issue #222. +
  • +
  • + JavaScript: in cpp lexer, add lexer.cpp.backquoted.strings=2 mode to treat ` back-quoted + strings as template literals which allow embedded ${expressions}. + Issue #94. +
  • +
  • + Python: fix lexing of rb'' and rf'' strings. + Issue #223, + Pull request #227. +
  • +
  • + Ruby: fix lexing of methods on numeric literals like '3.times' so the '.' and method name do not appear in numeric style. + Issue #225. +
  • +
+

+ Release 5.3.0 +

+
    +
  • + Released 27 December 2023. +
  • +
  • + Fix calling AddStaticLexerModule by defining as C++ instead of C which matches header. + Bug #2421. +
  • +
  • + Bash: Fix shift operator << incorrectly recognized as here-doc. + Issue #215. +
  • +
  • + Bash: Fix termination of '${' with first unquoted '}' instead of nesting. + Issue #216. +
  • +
  • + HTML: JavaScript double-quoted strings may escape line end with '\'. + Issue #214. +
  • +
  • + Lua: recognize --- doc comments. + Defined by LDoc. + Does not recognize --[[-- doc comments which seem less common. +
  • +
+

+ Release 5.2.9 +

+
    +
  • + Released 18 November 2023. +
  • +
  • + Xcode build settings changed to avoid problems with Xcode 15.0. +
  • +
+

+ Release 5.2.8 +

+
    +
  • + Released 5 November 2023. +
  • +
  • + Python: Update f-string handling to match PEP 701 and Python 3.12. + Controlled with property lexer.python.strings.f.pep.701. + Issue #150, + Pull request #209. +
  • +
  • + R: Fix escape sequence highlighting with change of for loop to while loop. + Issue #206, + Pull request #207. +
  • +
  • + Minimum supported macOS release increased to 10.13. +
  • +
+

+ Release 5.2.7 +

+
    +
  • + Released 22 September 2023. +
  • +
  • + Fix building on Windows with non-English environment. + Pull request #200. +
  • +
  • + Bash: fix line continuation for comments and when multiple backslashes at line end. + Issue #195. +
  • +
  • + Bash: treat += as operator and, inside arithmetic expressions, treat ++ and -- as operators. + Issue #197. +
  • +
  • + Bash: improve backslash handling inside backquoted command substitution and fix $ at end of backtick expression. + Issue #194. +
  • +
  • + Bash: treat words that are similar to numbers but invalid wholly as identifiers. + Issue #199. +
  • +
  • + Bash: consistently handle '-' options at line start and after '|' as identifiers. + Issue #202. +
  • +
  • + Bash: handle '-' options differently in [ single ] and [[ double ]] bracket constructs. + Issue #203. +
  • +
  • + F#: improve speed of folding long lines. + Issue #198. +
  • +
  • + HTML: fix invalid entity at line end and terminate invalid entity before invalid character. + Issue #192. +
  • +
+

+ Release 5.2.6 +

+
    +
  • + Released 26 July 2023. +
  • +
  • + Include empty word list names in value returned by DescribeWordListSets and SCI_DESCRIBEKEYWORDSETS. + Issue #175, + Pull request #176. +
  • +
  • + Bash: style here-doc end delimiters as SCE_SH_HERE_DELIM instead of SCE_SH_HERE_Q. + Issue #177. +
  • +
  • + Bash: allow '$' as last character in string. + Issue #180, + Pull request #181. +
  • +
  • + Bash: fix state after expansion. Highlight all numeric and file test operators. + Don't highlight dash in long option as operator. + Issue #182, + Pull request #183. +
  • +
  • + Bash: strict checking of special parameters ($*, $@, $$, ...) with property lexer.bash.special.parameter to specify + valid parameters. + Issue #184, + Pull request #186. +
  • +
  • + Bash: recognize keyword before redirection operators (< and >). + Issue #188, + Pull request #189. +
  • +
  • + Errorlist: recognize Bash diagnostic messages. +
  • +
  • + HTML: allow ASP block to terminate inside line comment. + Issue #185. +
  • +
  • + HTML: fix folding with JSP/ASP.NET <%-- comment. + Issue #191. +
  • +
  • + HTML: fix incremental styling of multi-line ASP.NET directive. + Issue #191. +
  • +
  • + Matlab: improve arguments blocks. + Add support for multiple arguments blocks. + Prevent "arguments" from being keyword in function declaration line. + Fix semicolon handling. + Pull request #179. +
  • +
  • + Visual Prolog: add support for embedded syntax with SCE_VISUALPROLOG_EMBEDDED + and SCE_VISUALPROLOG_PLACEHOLDER.
    + Styling of string literals changed with no differentiation between literals with quotes and those + that are prefixed with "@". + Quote characters are in a separate style (SCE_VISUALPROLOG_STRING_QUOTE) + to contents (SCE_VISUALPROLOG_STRING).
    + SCE_VISUALPROLOG_CHARACTER, SCE_VISUALPROLOG_CHARACTER_TOO_MANY, + SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR, SCE_VISUALPROLOG_STRING_EOL_OPEN, + and SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL were removed (replaced with + SCE_VISUALPROLOG_UNUSED[1-5]). + Pull request #178. +
  • +
+

+ Release 5.2.5 +

+
    +
  • + Released 31 May 2023. +
  • +
  • + Add CharacterSetArray constructor without setBase initial argument for common case + where this is setNone and the initialSet argument completely defines the characters. + This shortens and clarifies use of CharacterSetArray. +
  • +
  • + Bash: implement highlighting inside quoted elements and here-docs. + Controlled with properties lexer.bash.styling.inside.string, lexer.bash.styling.inside.backticks, + lexer.bash.styling.inside.parameter, and lexer.bash.styling.inside.heredoc. + Issue #154, + Issue #153, + Feature #1033. +
  • +
  • + Bash: add property lexer.bash.command.substitution to choose how to style command substitutions. + 0 → SCE_SH_BACKTICKS; + 1 → surrounding "$(" and ")" as operators and contents styled as bash code; + 2 → use distinct styles (base style + 64) for contents. + Choice (2) is a provisional feature and details may change before it is finalized. + Issue #153. +
  • +
  • + Bash: fix nesting of parameters (SCE_SH_PARAM) like ${var/$sub/"${rep}}"}. + Issue #154. +
  • +
  • + Bash: fix single character special parameters like $? by limiting style. + Issue #154. +
  • +
  • + Bash: treat "$$" as special parameter and end scalars before "$". + Issue #154. +
  • +
  • + Bash: treat "<<" in arithmetic contexts as left bitwise shift operator instead of here-doc. + Issue #137. +
  • +
  • + Batch: style SCE_BAT_AFTER_LABEL used for rest of line after label which is not executed. + Issue #148. +
  • +
  • + F#: Lex interpolated verbatim strings as verbatim. + Issue #156. +
  • +
  • + VB: allow multiline strings when lexer.vb.strings.multiline set. + Issue #151. +
  • +
+

+ Release 5.2.4 +

+
    +
  • + Released 13 March 2023. +
  • +
  • + C++: Fix failure to recognize keywords containing upper case. + Issue #149. +
  • +
  • + GDScript: Support % and $ node paths. + Issue #145, + Pull request #146. +
  • +
+

+ Release 5.2.3 +

+
    +
  • + Released 8 March 2023. +
  • +
  • + Add scripts/PromoteNew.bat script to promote .new files after checking. +
  • +
  • + Makefile: Remove 1024-byte line length limit.. +
  • +
  • + Ruby: Add new lexical classes for % literals SCE_RB_STRING_W (%w non-interpolable string array), + SCE_RB_STRING_I (%i non-interpolable symbol array), + SCE_RB_STRING_QI (%I interpolable symbol array), + and SCE_RB_STRING_QS (%s symbol). + Issue #124. +
  • +
  • + Ruby: Disambiguate %= which may be a quote or modulo assignment. + Issue #124, + Bug #1255, + Bug #2182. +
  • +
  • + Ruby: Fix additional fold level for single character in SCE_RB_STRING_QW. + Issue #132. +
  • +
  • + Ruby: Set SCE_RB_HERE_QQ for unquoted and double-quoted heredocs and + SCE_RB_HERE_QX for backticks-quoted heredocs. + Issue #134. +
  • +
  • + Ruby: Recognise #{} inside SCE_RB_HERE_QQ and SCE_RB_HERE_QX. + Issue #134. +
  • +
  • + Ruby: Improve regex and heredoc recognition. + Issue #136. +
  • +
  • + Ruby: Highlight #@, #@@ and #$ style interpolation. + Issue #140. +
  • +
  • + Ruby: Fix folding for multiple heredocs started on one line. + Fix folding when there is a space after heredoc opening delimiter. + Issue #135. +
  • +
  • + YAML: Remove 1024-byte line length limit. +
  • +
+

+ Release 5.2.2 +

+
    +
  • + Released 8 February 2023. +
  • +
  • + C++: Fix keywords that start with non-ASCII. Also affects other lexers. + Issue #130. +
  • +
  • + Matlab: Include more prefix and suffix characters in numeric literals. + Issue #120. +
  • +
  • + Matlab: More accurate treatment of line ends inside strings. Matlab and Octave are different here. + Issue #18. +
  • +
  • + Modula-3: Don't treat identifier suffix that matches keyword as keyword. + Issue #129. +
  • +
  • + Modula-3: Fix endless loop in folder. + Issue #128. +
  • +
  • + Modula-3: Fix access to lines beyond document end in folder. + Issue #131. +
  • +
  • + Python: Don't highlight match and case as keywords in contexts where they probably aren't used as keywords. + Pull request #122. +
  • +
  • + X12: Support empty envelopes. + Bug #2369. +
  • +
+

+ Release 5.2.1 +

+
    +
  • + Released 6 December 2022. +
  • +
  • + Update to Unicode 14. + Feature #1461. +
  • +
  • + Change default compilation optimization option to favour speed over space. + -O2 for MSVC and -O3 for gcc and clang. +
  • +
  • + Batch: Fix comments starting inside strings. + Issue #115. +
  • +
  • + F#: Lex signed numeric literals more accurately. + Issue #110, + Issue #111. +
  • +
  • + F#: Add specifiers for 64-bit integer and floating point literals. + Issue #112. +
  • +
  • + Markdown: Stop styling numbers at line start in PRECHAR style. + Issue #117. +
  • +
  • + PowerShell: Recognise numeric literals more accurately. + Issue #118. +
  • +
+

+ Release 5.2.0 +

+
    +
  • + Released 12 October 2022. +
  • +
  • + PowerShell: End comment before \r carriage return so \r and \n in same + SCE_POWERSHELL_DEFAULT style. + Pull request #99. +
  • +
  • + PowerShell: Fix character truncation bug that lead to 'ġ' styled as an operator since its low 8 bits + are equal to '!'. +
  • +
  • + R: Support hexadecimal, float exponent and number suffix. + Issue #101. +
  • +
  • + R: Highlight backticks. + Pull request #102. +
  • +
  • + R: Highlight raw strings. + Issue #100. +
  • +
  • + R: Optionally highlight escape sequences in strings. + Issue #100. +
  • +
  • + Fix early truncation from LexAccessor::GetRange and LexAccessor::GetRangeLowered. + Issue #17. +
  • +
+

+ Release 5.1.9 +

+
    +
  • + Released 27 August 2022. +
  • +
  • + Julia: Parse unicode forall and exists as identifiers #42314. + Pull request #98. +
  • +
  • + Julia: Parse apostrophe as char and not adjoint after exclamation. + Issue #97, + Pull request #98. +
  • +
  • + Properties: Don't set header flag for empty section. + Issue #96. +
  • +
+

+ Release 5.1.8 +

+
    +
  • + Released 10 July 2022. +
  • +
  • + F#: Recognize nested comments in F#. + Issue #93. +
  • +
  • + MS SQL: Recognize nested comments in Transact-SQL. + Issue #87. +
  • +
  • + MS SQL: Preference data types more consistently to not depend on how lexing is broken + up into segments. This is needed because there are keywords that are both data type + names and function names such as 'CHAR'. + Issue #90. +
  • +
  • + PowerShell: Fix single quoted strings to not treat backtick as escape. + Pull request #92. +
  • +
  • + Visual Prolog: Treat \r\n line ends the same as \n. This makes testing easier. + Add test case. + Issue #83. +
  • +
  • + Visual Prolog: Allow disabling verbatim strings. + Pull request #89. +
  • +
  • + Visual Prolog: Support backquoted strings. + Pull request #89. +
  • +
+

+ Release 5.1.7 +

+
    +
  • + Released 22 May 2022. +
  • +
  • + Add LexAccessor::StyleIndexAt to retrieve style values as unsigned to handle styles > 127 better. + Issue #61. +
  • +
  • + Associate more than one file extension with a setting for testing. + Issue #81. +
  • +
  • + CMake: Fix folding of "ElseIf". + Issue #77, + Pull request #78, + Bug #2213. +
  • +
  • + HTML: Fix folding of JavaScript doc comments. + Bug #2219. +
  • +
  • + Matlab: add "classdef" and "spmd" to folding keywords. + Pull request #70. +
  • +
  • + Matlab: handle "arguments" contextual keyword. + Pull request #70. +
  • +
  • + Matlab: improve support of class definition syntax. + Pull request #75. +
  • +
  • + Raku: fix escape detection. + Pull request #76. +
  • +
  • + Ruby: fix character sequence "?\\#" to not include '#' in SCE_RB_NUMBER as only second '\' is quoted. + Issue #69. +
  • +
  • + Ruby: improve styling of ternary expressions as commonly used. + Issue #69. +
  • +
  • + VHDL: support folding for VHDL 08 else-generate and case-generate. + Pull request #80. +
  • +
+

+ Release 5.1.6 +

+
    +
  • + Released 31 March 2022. +
  • +
  • + Implement conditional statements "if" and "match", comparison function "$(=", and "FileNameExt" + property in TestLexers to allow varying lexer properties over different files. + Issue #62. +
  • +
  • + Add LexAccessor::BufferStyleAt to retrieve style values to simplify logic and + improve performance. + Issue #54. +
  • +
  • + Markdown: Optionally style all of Markdown header lines. + Enabled with lexer.markdown.header.eolfill=1. + Issue #60. +
  • +
  • + Ruby: Fix operator method styling so next word not treated as method name. + Issue #65. +
  • +
  • + Ruby: Fix folding for Ruby 3 endless method definition. + Issue #65. +
  • +
  • + Ruby: Fold string array SCE_RB_STRING_QW. + Issue #65. +
  • +
  • + Ruby: Fix final \n in indented heredoc to be SCE_RB_HERE_Q. + Issue #66. +
  • +
  • + Ruby: Fix heredoc recognition when '.' and ',' used in method calls and after SCE_RB_GLOBAL. + Classify word after heredoc delimiter instead of styling as keyword. + Issue #67. +
  • +
  • + Ruby: Improve method highlighting so method name is styled as SCE_RB_DEFNAME and class/object + is styled appropriately. + Issue #68. +
  • +
+

+ Release 5.1.5 +

+
    +
  • + Released 9 February 2022. +
  • +
  • + Bash: Treat \r\n line ends the same as \n. This makes testing easier. + Issue #57. +
  • +
  • + Batch: Recognise "::" comments when second command on line. + Bug #2304. +
  • +
  • + F#: Recognise format specifiers in interpolated strings and %B for binary. + Issue #46. +
  • +
  • + F#: More accurate line-based folding. + Issue #56. +
  • +
  • + HTML: Fix folding inside script blocks. + Issue #47, + Issue #53. +
  • +
  • + Inno Setup: Fix multiline comments in code. + Issue #44. +
  • +
  • + Python: Add attribute style with properties lexer.python.identifier.attributes and + lexer.python.decorator.attributes. + Pull request #49. +
  • +
  • + Allow choice of object file directory with makefile by setting DIR_O. + Issue #50. +
  • +
+

+ Release 5.1.4 +

+
    +
  • + Released 7 December 2021. +
  • +
  • + Add AsciiDoc lexer. + Pull request #39. +
  • +
  • + Add GDScript lexer. + Some behaviour and lexical states may change before this lexer is stable. + Pull request #41. +
  • +
  • + Fix strings ending in escaped '\' in F#. + Issue #38. +
  • +
  • + Better handling of bad terminators and folding for X12. + Feature #1420. +
  • +
+

+ Release 5.1.3 +

+
    +
  • + Released 8 November 2021. +
  • +
  • + Fix parsing of 128-bit integer literals in Rust. + Issue #33. +
  • +
  • + Fix different styles between \r and \n at end of line comments for Rust. + Issue #34. +
  • +
  • + For Rust, don't go past end when file ends with unterminated block comment. + Issue #35. +
  • +
+

+ Release 5.1.2 +

+
    +
  • + Released 23 September 2021. +
  • +
  • + Implement conditional group rules in CSS. + Issue #25, + Pull request #28. +
  • +
  • + Allow F# triple-quoted strings to interpolate string literals. + Issue #21. +
  • +
  • + Highlight F# printf specifiers in type-checked interpolated strings. + Issue #24. +
  • +
  • + Fix styling for Inno Setup scripts handling unterminated strings, + message sections, and avoid terminating comments between CR and LF. + Pull request #29. + Feature #1415. +
  • +
  • + Fix Markdown hang when document ends with "`", "*", "_", or similar. + Issue #23. +
  • +
  • + Treat '.' as an operator instead of part of a word for PHP. + Issue #22. + Bug #2225. +
  • +
  • + Check PHP numeric literals, showing invalid values with default style instead of numeric. + Issue #20. +
  • +
  • + For PHP, recognize start of comment after numeric literal. + Issue #20. + Bug #2143. +
  • +
  • + For PHP, recognize PHP code within JavaScript strings. + Pull request #27. +
  • +
+

+ Release 5.1.1 +

+
    +
  • + Released 26 July 2021. +
  • +
  • + On 32-bit Win32 using Visual C++ projects, stop exported functions ending with @n causing failures with GetProcAddress. +
  • +
  • + Fixed crash when calling TagsOfStyle on C++ lexer after allocating substyles. +
  • +
  • + Fixed folding for Julia which could be inconsistent depending on range folded. + Added SCE_JULIA_KEYWORD4 and SCE_JULIA_TYPEOPERATOR lexical styles and + changed keyword set 4 from "Raw string literals" to "Built in functions". + Property lexer.julia.string.interpolation removed. + Updated set of characters for identifiers. + Pull request #13. +
  • +
  • + Fixed Markdown emphasis spans to only be recognized when closed in same paragraph. + Bug #1216. +
  • +
  • + Fixed Markdown code block to terminate when end marker is indented. + Display all of end marker in code block style. + Only recognize inline code when closed in same paragraph. + Bug #2247. +
  • +
  • + Fixed Matlab to not allow escape sequences in double-quoted strings. + Issue #18. +
  • +
  • + Support flexible heredoc and nowdoc syntax for PHP. + Issue #19. +
  • +
  • + Enabled '_' digit separator in numbers for PHP. + Issue #19. +
  • +
  • + Stop styling attributes as comments for PHP. + Issue #19. +
  • +
+

+ Release 5.1.0 +

+
    +
  • + Released 23 June 2021. +
  • +
  • + This is a stable release. The Lexilla protocol should remain compatible through 5.x releases. +
  • +
  • + Fixed bugs with styling Erlang by handling \n and \r\n line endings consistently. +
  • +
  • + Fixed folding for F# open statements and for strings that contain comment prefixes. +
  • +
  • + Format specifiers lexed in F# strings. +
  • +
  • + Fixed folding for ASP files where scripts were treated inconsistently when '<%' was included + or not included in range examined. +
  • +
  • + Fixed folding of Raku heredocs that start with "q:to" or "qq:to". +
  • +
  • + Fixed folding at end of Ruby files where these is no final new line. +
  • +
  • + Made folding of Tcl files more consistent by always treating completely empty lines as whitespace. +
  • +
  • + Fixed styling of "a:b" with no spaces in YAML as a single piece of text instead of a key-value pair. + Pull request #15. +
  • +
+

+ Release 5.0.3 +

+
    +
  • + Released 2 June 2021. +
  • +
  • + Add namespace feature with GetNameSpace function. +
  • +
  • + Add Julia lexer. + Feature #1380. +
  • +
  • + Fix transition to comment for --> inside JavaScript string. + Bug #2207. +
  • +
  • + Fix variable expansion in Batch. + Issue #4. +
  • +
  • + Fix empty link titles in Markdown. + Bug #2235. + Also fix detection of whether the previous line had content which treated '\n' and '\r\n' line endings differently. +
  • +
  • + Remove nested comment and long string support as these were removed from Lua. + Bug #2205. +
  • +
  • + Update to Unicode 13. + Feature #1379. +
  • +
  • + AddStaticLexerModule function adds a static lexer to Lexilla's list. +
  • +
  • + On Win32 enable hardware-enforced stack protection. + Feature #1405. +
  • +
  • + On 32-bit Win32 using g++, stop exported functions ending with @n causing failures with GetProcAddress. + Issue #10. +
  • +
+

+ Release 5.0.2 +

+
    +
  • + Released 23 April 2021. +
  • +
  • + Fix assertion in cpp lexer handling of preprocessor. + Empty preprocessor statement '#' caused preprocessor history to be stored on incorrect line number. + Dangling #else or #elif without corresponding #if led to inconsistent state. + Change treatment of empty preprocessor statement to set subsequent line end characters in + preprocessor style as this is more consistent with other preprocessor directives and avoids + differences between \n and \r\n line ends. + Bug #2245. +
  • +
+

+ Release 5.0.1 +

+
    +
  • + Released 9 April 2021. +
  • +
  • + Add LexerNameFromID function to Lexilla protocol as optional and temporary to + help applications migrate to Lexilla. + It is marked deprecated and will be removed in a future release. +
  • +
  • + The cpp lexer supports XML styled comment doc keywords. + Pull request #2. +
  • +
  • + The errorlist lexer detects NMAKE fatal errors and Microsoft linker errors as SCE_ERR_MS. +
  • +
+

+ Release 5.0.0 +

+
    +
  • + Released 5 March 2021. +
  • +
  • + First version that separates Lexilla from Scintilla. + Each of the 3 projects now has a separate history page but history before 5.0.0 remains combined. +
  • +
  • + Lexer added for F#. +
  • +
+

+ Lexilla became a separate project at this point. +

+

+ Release 4.4.6 +

+
    +
  • + Released 1 December 2020. +
  • +
  • + Fix building with Xcode 12. + Bug #2187. +
  • +
+

+ Release 4.4.5 +

+
    +
  • + Released 11 September 2020. +
  • +
  • + Lexilla interface supports setting initialisation properties on lexer libraries with + SetLibraryProperty and GetLibraryPropertyNames functions. + These are called by SciTE which will forward properties to lexer libraries that are prefixed with + "lexilla.context.". +
  • +
  • + Allow cross-building for GTK by choosing pkg-config. + Bug #2189. +
  • +
  • + On GTK, allow setting CPPFLAGS (and LDFLAGS for SciTE) to support hardening. + Bug #2191. +
  • +
  • + Changed SciTE's indent.auto mode to set tab size to indent size when file uses tabs for indentation. + Bug #2198. +
  • +
  • + Fix position of marker symbols for SC_MARGIN_RTEXT which were being moved based on + width of text. +
  • +
  • + Fixed bug on Win32 where cursor was flickering between hand and text over an + indicator with hover style. + Bug #2170. +
  • +
  • + Fixed bug where hovered indicator was not returning to non-hover + appearance when mouse moved out of window or into margin. + Bug #2193. +
  • +
  • + Fixed bug where a hovered INDIC_TEXTFORE indicator was not applying the hover + colour to the whole range. + Bug #2199. +
  • +
  • + Fixed bug where gradient indicators were not showing hovered appearance. +
  • +
  • + Fixed bug where layout caching was ineffective. + Bug #2197. +
  • +
  • + For SciTE, don't show the output pane for quiet jobs. + Feature #1365. +
  • +
  • + Support command.quiet for SciTE on GTK. + Feature #1365. +
  • +
  • + Fixed a bug in SciTE with stack balance when a syntax error in the Lua startup script + caused continuing failures to find functions after the syntax error was corrected. + Bug #2176. +
  • +
  • + Added method for iterating through multiple vertical edges: SCI_GETMULTIEDGECOLUMN. + Feature #1350. +
  • +
+

+ Release 4.4.4 +

+
    +
  • + Released 21 July 2020. +
  • +
  • + End of line annotations implemented. + Bug #2141. +
  • +
  • + Add SCI_BRACEMATCHNEXT API. + Feature #1368. +
  • +
  • + The latex lexer supports lstlisting environment that is similar to verbatim. + Feature #1358. +
  • +
  • + For SciTE on Linux, place liblexilla.so and libscintilla.so in /usr/lib/scite. + Bug #2184. +
  • +
  • + Round SCI_TEXTWIDTH instead of truncating as this may be more accurate when sizing application + elements to match text. + Feature #1355. +
  • +
  • + Display DEL control character as visible "DEL" block like other control characters. + Feature #1369. +
  • +
  • + Allow caret width to be up to 20 pixels. + Feature #1361. +
  • +
  • + SciTE on Windows adds create.hidden.console option to stop console window flashing + when Lua script calls os.execute or io.popen. +
  • +
  • + Fix translucent rectangle drawing on Qt. When drawing a translucent selection, there were edge + artifacts as the calls used were drawing outlines over fill areas. Make bottom and right borders on + INDIC_ROUNDBOX be same intensity as top and left. + Replaced some deprecated Qt calls with currently supported calls. +
  • +
  • + Fix printing on Windows to use correct text size. + Bug #2185. +
  • +
  • + Fix bug on Win32 where calling WM_GETTEXT for more text than in document could return + less text than in document. +
  • +
  • + Fixed a bug in SciTE with Lua stack balance causing failure to find + functions after reloading script. + Bug #2176. +
  • +
+

+ Release 4.4.3 +

+
    +
  • + Released 3 June 2020. +
  • +
  • + Fix syntax highlighting for SciTE on Windows by setting executable directory for loading Lexilla. + Bug #2181. +
  • +
+

+ Release 4.4.2 +

+
    +
  • + Released 2 June 2020. +
  • +
  • + On Cocoa using Xcode changed Lexilla.dylib install path to @rpath as would otherwise try /usr/lib which + won't work for sandboxed applications. +
  • +
  • + On Cocoa using Xcode made work on old versions of macOS by specifying deployment target as 10.8 + instead of 10.15. +
  • +
  • + On Win32 fix static linking of Lexilla by specifying calling convention in Lexilla.h. +
  • +
  • + SciTE now uses default shared library extension even when directory contains '.'. +
  • +
+

+ Release 4.4.0 +

+
    +
  • + Released 1 June 2020. +
  • +
  • + Added Xcode project files for Lexilla and Scintilla with no lexers (cocoa/Scintilla). +
  • +
  • + For GTK, build a shared library with no lexers libscintilla.so or libscintilla.dll. +
  • +
  • + Lexilla used as a shared library for most builds of SciTE except for the single file executable on Win32. + On GTK, Scintilla shared library used. + LexillaLibrary code can be copied out of SciTE for other applications that want to interface to Lexilla. +
  • +
  • + Constants in Scintilla.h can be disabled with SCI_DISABLE_AUTOGENERATED. +
  • +
  • + Implement per-monitor DPI Awareness on Win32 so both Scintilla and SciTE + will adapt to the display scale when moved between monitors. + Applications should forward WM_DPICHANGED to Scintilla. + Bug #2171, + Bug #2063. +
  • +
  • + Optimized performance when opening huge files. + Feature #1347. +
  • +
  • + Add Appearance and Contrast properties to SciTE that allow customising visuals for dark mode and + high contrast modes. +
  • +
  • + Fixed bug in Batch lexer where a single character line with a single character line end continued + state onto the next line. +
  • +
  • + Added SCE_ERR_GCC_EXCERPT style for GCC 9 diagnostics in errorlist lexer. +
  • +
  • + Fixed buffer over-read bug with absolute references in MMIXAL lexer. + Bug #2019. +
  • +
  • + Fixed bug with GTK on recent Linux distributions where underscores were invisible. + Bug #2173. +
  • +
  • + Fixed GTK on Linux bug when pasting from closed application. + Bug #2175. +
  • +
  • + Fixed bug in SciTE with Lua stack balance. + Bug #2176. +
  • +
  • + For macOS, SciTE reverts to running python (2) due to python3 not being available in the sandbox. +
  • +
+

+ Release 4.3.3 +

+
    +
  • + Released 27 April 2020. +
  • +
  • + Added Visual Studio project files for Lexilla and Scintilla with no lexers. +
  • +
  • + Add methods for iterating through the marker handles and marker numbers on a line: + SCI_MARKERHANDLEFROMLINE and SCI_MARKERNUMBERFROMLINE. + Feature #1344. +
  • +
  • + Assembler lexers asm and as can change comment character with lexer.as.comment.character property. + Feature #1314. +
  • +
  • + Fix brace styling in Batch lexer so that brace matching works. + Bug #1624, + Bug #1906, + Bug #1997, + Bug #2065. +
  • +
  • + Change Perl lexer to style all line ends of comment lines in comment line style. + Previously, the last character was in default style which made the characters in + \r\n line ends have mismatching styles. + Bug #2164. +
  • +
  • + When a lexer has been set with SCI_SETILEXER, fix SCI_GETLEXER and avoid + sending SCN_STYLENEEDED notifications. +
  • +
  • + On Win32 fix handling Japanese IME input when both GCS_COMPSTR and + GCS_RESULTSTR set. +
  • +
  • + With Qt on Win32 add support for line copy format on clipboard, compatible with Visual Studio. + Bug #2167. +
  • +
  • + On Qt with default encoding (ISO 8859-1) fix bug where 'µ' (Micro Sign) case-insensitively matches '?' + Bug #2168. +
  • +
  • + On GTK with Wayland fix display of windowed IME. + Bug #2149. +
  • +
  • + For Python programs, SciTE defaults to running python3 on Unix and pyw on Windows which will run + the most recently installed Python in many cases. + Set the "python.command" property to override this. + Scripts distributed with Scintilla and SciTE are checked with Python 3 and may not work with Python 2. +
  • +
+

+ Release 4.3.2 +

+
    +
  • + Released 6 March 2020. +
  • +
  • + On Win32 fix new bug that treated all dropped text as rectangular. +
  • +
+

+ Release 4.3.1 +

+
    +
  • + Released 4 March 2020. +
  • +
  • + Add default argument for StyleContext::GetRelative. + Feature #1336. +
  • +
  • + Fix drag and drop between different encodings on Win32 by always providing CF_UNICODETEXT only. + Bug #2151. +
  • +
  • + Automatically scroll while dragging text. + Feature #497. +
  • +
  • + On Win32, the numeric keypad with Alt pressed can be used to enter characters by number. + This can produce unexpected results in non-numlock mode when function keys are assigned. + Potentially problematic keys like Alt+KeypadUp are now ignored. + Bug #2152. +
  • +
  • + Crash fixed with Direct2D on Win32 when updating driver. + Bug #2138. +
  • +
  • + For SciTE on Win32, fix crashes when Lua script closes application. + Bug #2155. +
  • +
+

+ Release 4.3.0 +

+
    +
  • + Released 16 January 2020. +
  • +
  • + Lexers made available as Lexilla library. + TestLexers program with tests for Lexilla and lexers added in lexilla/test. +
  • +
  • + SCI_SETILEXER implemented to use lexers from Lexilla or other sources. +
  • +
  • + ILexer5 interface defined provisionally to support use of Lexilla. + The details of this interface may change before being stabilised in Scintilla 5.0. +
  • +
  • + SCI_LOADLEXERLIBRARY implemented on Cocoa. +
  • +
  • + Build Scintilla with SCI_EMPTYCATALOGUE to avoid making lexers available. +
  • +
  • + Lexer and folder added for Raku language. + Feature #1328. +
  • +
  • + Don't clear clipboard before copying text with Qt. + Bug #2147. +
  • +
  • + On Win32, remove support for CF_TEXT clipboard format as Windows will convert to + CF_UNICODETEXT. +
  • +
  • + Improve IME behaviour on GTK. + Set candidate position for windowed IME. + Improve location of candidate window. + Prevent movement of candidate window while typing. + Bug #2135. +
  • +
+

+ Release 4.2.3 +

+
    +
  • + Released 11 December 2019. +
  • +
  • + Fix failure in SciTE's Complete Symbol command. +
  • +
+

+ Release 4.2.2 +

+
    +
  • + Released 7 December 2019. +
  • +
  • + Move rather than grow selection when insertion at start. + Bug #2140. +
  • +
  • + Allow target to have virtual space. + Add methods for finding the virtual space at start and end of multiple selections. + Feature #1316. +
  • +
  • + SciTE on Win32 adds mouse button "Forward" and "Backward" key definitions for use in + properties like user.shortcuts. + Feature #1317. +
  • +
  • + Lexer and folder added for Hollywood language. + Feature #1324. +
  • +
  • + HTML lexer treats custom tags from HTML5 as known tags. These contain "-" like "custom-tag". + Feature #1299. +
  • +
  • + HTML lexer fixes bug with some non-alphabetic characters in unknown tags. + Feature #1320. +
  • +
  • + Fix bug in properties file lexer where long lines were only styled for the first 1024 characters. + Bug #1933. +
  • +
  • + Ruby lexer recognizes squiggly heredocs. + Feature #1326. +
  • +
  • + Avoid unnecessary IME caret movement on Win32. + Feature #1304. +
  • +
  • + Clear IME state when switching language on Win32. + Bug #2137. +
  • +
  • + Fixed drawing of translucent rounded rectangles on Win32 with Direct2D. + Bug #2144. +
  • +
  • + Setting rectangular selection made faster. + Bug #2130. +
  • +
  • + SciTE reassigns *.s extension to the GNU Assembler language from the S+ statistical language. +
  • +
+

+ Release 4.2.1 +

+
    +
  • + Released 24 October 2019. +
  • +
  • + Add SCI_SETTABMINIMUMWIDTH to set the minimum width of tabs. + This allows minimaps or overviews to be laid out to match the full size editing view. + Bug #2118. +
  • +
  • + SciTE enables use of SCI_ commands in user.context.menu. +
  • +
  • + XML folder adds fold.xml.at.tag.open option to fold tags at the start of the tag "<" instead of the end ">". + Bug #2128. +
  • +
  • + Metapost lexer fixes crash with 'interface=none' comment. + Bug #2129. +
  • +
  • + Perl lexer supports indented here-docs. + Bug #2121. +
  • +
  • + Perl folder folds qw arrays. + Feature #1306. +
  • +
  • + TCL folder can turn off whitespace flag by setting fold.compact property to 0. + Bug #2131. +
  • +
  • + Optimize setting up keyword lists in lexers. + Feature #1305. +
  • +
  • + Updated case conversion and character categories to Unicode 12.1. + Feature #1315. +
  • +
  • + On Win32, stop the IME candidate window moving unnecessarily and position it better.
    + Stop candidate window overlapping composition text and taskbar.
    + Position candidate window closer to composition text.
    + Stop candidate window moving while typing.
    + Align candidate window to target part of composition text.
    + Stop Google IME on Windows 7 moving while typing.
    + Bug #2120. + Feature #1300. +
  • +
+

+ Release 4.2.0 +

+
    +
  • + Released 5 July 2019. +
  • +
  • + Scintilla.iface adds line and pointer types, increases use of the position type, uses enumeration + types in methods and properties, and adds enumeration aliases to produce better CamelCase + identifiers. + Feature #1297. +
  • +
  • + Source of input (direct / IME composition / IME result) reported in SCN_CHARADDED so applications + can treat temporary IME composition input differently. + Bug #2038. +
  • +
  • + Lexer added for DataFlex. + Feature #1295. +
  • +
  • + Matlab lexer now treats keywords as case-sensitive. + Bug #2112. +
  • +
  • + SQL lexer fixes single quoted strings where '" (quote, double quote) was seen as continuing the string. + Bug #2098. +
  • +
  • + Platform layers should use InsertCharacter method to perform keyboard and IME input, replacing + AddCharUTF method. + Feature #1293. +
  • +
  • + Add CARETSTYLE_BLOCK_AFTER option to always display block caret after selection. + Bug #1924. +
  • +
  • + On Win32, limit text returned from WM_GETTEXT to the length specified in wParam. + This could cause failures when using assistive technologies like NVDA. + Bug #2110, + Bug #2114. +
  • +
  • + Fix deletion of isolated invalid bytes. + Bug #2116. +
  • +
  • + Fix position of line caret when overstrike caret set to block. + Bug #2106. +
  • +
+

+ Release 4.1.7 +

+
    +
  • + Released 13 June 2019. +
  • +
  • + Fixes an incorrect default setting in SciTE which caused multiple visual features to fail to display. +
  • +
+

+ Release 4.1.6 +

+
    +
  • + Released 10 June 2019. +
  • +
  • + For Visual C++ 2019, /std:c++latest now includes some C++20 features so switch to /std:c++17. +
  • +
  • + SciTE supports editing files larger than 2 gigabytes when built as a 64-bit application. +
  • +
  • + Lexer added for X12. + Feature #1280. +
  • +
  • + CMake folder folds function - endfunction. + Feature #1289. +
  • +
  • + VB lexer adds support for VB2017 binary literal &B and digit separators 123_456. + Feature #1288. +
  • +
  • + Improved performance of line folding code on large files when no folds are contracted. + This improves the time taken to open or close large files. +
  • +
  • + Fix bug where changing identifier sets in lexers preserved previous identifiers. +
  • +
  • + Fixed bug where changing to Unicode would rediscover line end positions even if still + sticking to ASCII (not Unicode NEL, LS, PS) line ends. + Only noticeable on huge files with over 100,000 lines. +
  • +
  • + Changed behaviour of SCI_STYLESETCASE(*,SC_CASE_CAMEL) so that it only treats 'a-zA-Z' + as word characters because this covers the feature's intended use (viewing case-insensitive ASCII-only + keywords in a specified casing style) and simplifies the behaviour and code. + Feature #1238. +
  • +
  • + In SciTE added Camel case option "case:c" for styles to show keywords with initial capital. +
  • +
+

+ Release 4.1.5 +

+
    +
  • + Released 17 April 2019. +
  • +
  • + On Win32, removed special handling of non-0 wParam to WM_PAINT. +
  • +
  • + Implement high-priority idle on Win32 to make redraw smoother and more efficient. +
  • +
  • + Add vertical bookmark symbol SC_MARK_VERTICALBOOKMARK. + Feature #1276. +
  • +
  • + Set default fold display text SCI_SETDEFAULTFOLDDISPLAYTEXT(text). + Feature #1272. +
  • +
  • + Add SCI_SETCHARACTERCATEGORYOPTIMIZATION API to optimize speed + of character category features like determining whether a character is a space or number + at the expense of memory. + Feature #1259. +
  • +
  • + Improve the styling of numbers in Nim. + Feature #1268. +
  • +
  • + Fix exception when inserting DBCS text. + Bug #2093. +
  • +
  • + Improve performance of accessibility on GTK. + Bug #2094. +
  • +
  • + Fix text reported for deletion with accessibility on GTK. + Bug #2095. +
  • +
  • + Fix flicker when inserting primary selection on GTK. + Bug #2087. +
  • +
  • + Support coloured text in Windows 8.1+. + Feature #1277. +
  • +
  • + Avoid potential long hangs with idle styling for huge documents on Cocoa and GTK. +
  • +
+

+ Release 4.1.4 +

+
    +
  • + Released 7 March 2019. +
  • +
  • + Calltips implemented on Qt. + Bug #1548. +
  • +
  • + Block caret in overtype mode SCI_SETCARETSTYLE(caretStyle | CARETSTYLE_OVERSTRIKE_BLOCK). + Feature #1217. +
  • +
  • + SciTE supports changing caret style via caret.style property. + Feature #1264. +
  • +
  • + Lexer added for .NET's Common Intermediate Language CIL. + Feature #1265. +
  • +
  • + The C++ lexer, with styling.within.preprocessor on, now interprets "(" in preprocessor "#if(" + as an operator instead of part of the directive. This improves folding as well which could become + unbalanced. +
  • +
  • + Fix raw strings in Nim. + Feature #1253. +
  • +
  • + Fix inconsistency with dot styling in Nim. + Feature #1260. +
  • +
  • + Enhance the styling of backticks in Nim. + Feature #1261. +
  • +
  • + Enhance raw string identifier styling in Nim. + Feature #1262. +
  • +
  • + Fix fold behaviour with comments in Nim. + Feature #1254. +
  • +
  • + Fix TCL lexer recognizing '"' after "," inside a bracketed substitution. + Bug #1947. +
  • +
  • + Fix garbage text from SCI_MOVESELECTEDLINESUP and SCI_MOVESELECTEDLINESDOWN + for rectangular or thin selection by performing no action. + Bug #2078. +
  • +
  • + Ensure container notified if Insert pressed when caret off-screen. + Bug #2083. +
  • +
  • + Fix memory leak when checking running instance on GTK. + Feature #1267. +
  • +
  • + Platform layer font cache removed on Win32 as there is a platform-independent cache. +
  • +
  • + SciTE for GTK easier to build on macOS. + Bug #2084. +
  • +
+

+ Release 4.1.3 +

+
    +
  • + Released 10 January 2019. +
  • +
  • + Add SCI_SETCOMMANDEVENTS API to allow turning off command events as they + can be a significant performance cost. +
  • +
  • + Improve efficiency of idle wrapping by wrapping in blocks as large as possible while + still remaining responsive. +
  • +
  • + Updated case conversion and character categories to Unicode 11. +
  • +
  • + Errorlist lexer recognizes negative line numbers as some programs show whole-file + errors occurring on line -1. + SciTE's parsing of diagnostics also updated to handle this case. +
  • +
  • + Added "nim" lexer (SCLEX_NIM) for the Nim language which was previously called Nimrod. + For compatibility, the old "nimrod" lexer is still present but is deprecated and will be removed at the + next major version. + Feature #1242. +
  • +
  • + The Bash lexer implements substyles for multiple sets of keywords and supports SCI_PROPERTYNAMES. + Bug #2054. +
  • +
  • + The C++ lexer interprets continued preprocessor lines correctly by reading all of + the logical line. + Bug #2062. +
  • +
  • + The C++ lexer interprets preprocessor arithmetic expressions containing multiplicative and additive + operators correctly by following operator precedence rules. + Bug #2069. +
  • +
  • + The EDIFACT lexer handles message groups as well as messages. + Feature #1247. +
  • +
  • + For SciTE's Find in Files, allow case-sensitivity and whole-word options when running + a user defined command. + Bug #2053. +
  • +
  • + Notify with SC_UPDATE_SELECTION when user performs a multiple selection add. +
  • +
  • + On macOS 10.14 Cocoa, fix incorrect horizontal offset. + Bug #2022. +
  • +
  • + On Cocoa, fix a crash that occurred when entering a dead key diacritic then a character + that can not take that diacritic, such as option+e (acute accent) followed by g. + Bug #2061. +
  • +
  • + On Cocoa, use dark info bar background when system is set to Dark Appearance. + Bug #2055. +
  • +
  • + Fixed a crash on Cocoa in bidirectional mode where some patterns of invalid UTF-8 + caused failures to create Unicode strings. +
  • +
  • + SCI_MARKERADD returns -1 for invalid lines as documented instead of 0. + Bug #2051. +
  • +
  • + Improve performance of text insertion when Unicode line indexing off. +
  • +
  • + For Qt on Windows, stop specifying -std:c++latest as that is no longer needed + to enable C++17 with MSVC 2017 and Qt 5.12 and it caused duplicate flag warnings. +
  • +
  • + On Linux, enable Lua to access dynamic libraries. + Bug #2058. +
  • +
+

+ Release 4.1.2 +

+
    +
  • + Released 2 October 2018. +
  • +
  • + C++ lexer fixes evaluation of "#elif". + Bug #2045. +
  • +
  • + Markdown lexer fixes highlighting of non-ASCII characters in links. +
  • +
  • + SciTE on Win32 drops menukey feature, makes Del key work again in find and replace strips + and disables F5 while command running. + Bug #2044. +
  • +
+

+ Release 4.1.1 +

+
    +
  • + Released 9 September 2018. +
  • +
  • + Optional indexing of line starts in UTF-8 documents by UTF-32 code points and UTF-16 code units added. + This can improve performance for clients that provide UTF-32 or UTF-16 interfaces or that need to interoperate + with UTF-32 or UTF-16 components. +
  • +
  • + Lexers added for SAS and Stata. + Feature #1185. +
  • +
  • + Shell folder folds "if", "do", and "case". + Feature #1144. +
  • +
  • + SciTE's menukey feature implemented on Windows. +
  • +
  • + For SciTE on Windows, user defined strip lists are now scrollable. + Cursor no longer flickers in edit and combo boxes. + Focus in and out events occur for combo boxes. +
  • +
  • + Fix a leak in the bidirectional code on Win32. +
  • +
  • + Fix crash on Win32 when switching technology to default after setting bidirectional mode. +
  • +
  • + Fix margin cursor on Cocoa to point more accurately. +
  • +
  • + Fix SciTE crash on GTK+ when using director interface. +
  • +
+

+ Release 4.1.0 +

+
    +
  • + Released 19 June 2018. +
  • +
  • + Experimental and incomplete support added for bidirectional text on Windows using DirectWrite and Cocoa for + UTF-8 documents by calling SCI_SETBIDIRECTIONAL(SC_BIDIRECTIONAL_L2R). + This allows documents that contain Arabic or Hebrew to be edited more easily in a way that is similar + to other editors. +
  • +
  • + INDIC_GRADIENT and INDIC_GRADIENTCENTRE indicator types added. + INDIC_GRADIENT starts with a specified colour and alpha at top of line and fades + to fully transparent at bottom. + INDIC_GRADIENTCENTRE starts with a specified colour and alpha at centre of line and fades + to fully transparent at top and bottom. +
  • +
  • + Wrap indent mode SC_WRAPINDENT_DEEPINDENT added which indents two tabs from previous line. +
  • +
  • + Indicators are drawn for line end characters when displayed. +
  • +
  • + Most invalid bytes in DBCS encodings are displayed as blobs to make problems clear + and ensure something is shown. +
  • +
  • + On Cocoa, invalid text in DBCS encodings will be interpreted through the + single-byte MacRoman encoding as that will accept any byte. +
  • +
  • + Diff lexer adds styles for diffs containing patches. +
  • +
  • + Crashes fixed on macOS for invalid DBCS characters when dragging text, + changing case of text, case-insensitive searching, and retrieving text as UTF-8. +
  • +
  • + Regular expression crash fixed on macOS when linking to libstdc++. +
  • +
  • + SciTE on GTK+, when running in single-instance mode, now forwards all command line arguments + to the already running instance. + This allows "SciTE filename -goto:line" to work. +
  • +
+

+ Release 4.0.5 +

+
    +
  • + Released 10 May 2018. +
  • +
  • + Add experimental SC_DOCUMENTOPTION_TEXT_LARGE option to accommodate documents larger than + 2 GigaBytes. +
  • +
  • + Additional print option SC_PRINT_SCREENCOLOURS prints with the same colours used on screen + including line numbers. +
  • +
  • + SciTE can read settings in EditorConfig format when enabled with editor.config.enable property. +
  • +
  • + EDIFACT lexer adds property lexer.edifact.highlight.un.all to highlight all UN* segments. + Feature #1166. +
  • +
  • + Fortran folder understands "change team" and "endteam". + Feature #1216. +
  • +
  • + Set the last X chosen when SCI_REPLACESEL called to ensure macros work + when text insertion followed by caret up or down. +
  • +
  • + Bugs fixed in regular expression searches in Scintilla where some matches did not occur in an + effort to avoid infinite loops when replacing on empty matches like "^" and "$". + Applications should always handle empty matches in a way that avoids infinite loops, commonly + by incrementing the search position after replacing an empty match. + SciTE fixes a bug where replacing "^" always matched on the first line even when it was an + "in selection" replace and the selection started after the line start. +
  • +
  • + Bug fixed in SciTE where invalid numeric properties could crash. +
  • +
  • + Runtime warnings fixed with SciTE on GTK after using Find in Files. +
  • +
  • + SciTE on Windows find and replace strips place caret at end of text after search. +
  • +
  • + Bug fixed with SciTE on macOS where corner debris appeared in the margin when scrolling. + Fixed by not completely hiding the status bar so the curved corner is no longer part of the + scrolling region. + By default, 4 pixels of the status bar remain visible and this can be changed with + the statusbar.minimum.height property or turned off if the debris are not a problem by + setting the property to 0. +
  • +
+

+ Release 4.0.4 +

+
    +
  • + Released 10 April 2018. +
  • +
  • + On Win32, the standard makefiles build a libscintilla static library as well as the existing dynamic libraries. + The statically linked version of SciTE, Sc1, links to this static library. A new file, ScintillaDLL.cxx, provides + the DllMain function required for a stand-alone Scintilla DLL. Build and project files should include this + file when producing a DLL and omit it when producing a static library or linking Scintilla statically. + The STATIC_BUILD preprocessor symbol is no longer used. +
  • +
  • + On Win32, Direct2D support is no longer automatically detected during build. + DISABLE_D2D may still be defined to remove Direct2D features. +
  • +
  • + In some cases, invalid UTF-8 is handled in a way that is a little friendlier. + For example, when copying to the clipboard on Windows, an invalid lead byte will be copied as the + equivalent ISO 8859-1 character and will not hide the following byte. + Feature #1211. +
  • +
  • + Lexer added for the Maxima computer algebra language. + Feature #1210. +
  • +
  • + Fix hang in Lua lexer when lexing a label up to the terminating "::". + Bug #1999. +
  • +
  • + Lua lexer matches identifier chains with dots and colons. + Bug #1952. +
  • +
  • + For rectangular selections, pressing Home or End now moves the caret to the Home or End + position instead of the limit of the rectangular selection. +
  • +
  • + Fix move-extends-selection mode for rectangular and line selections. +
  • +
  • + On GTK+, change lifetime of selection widget to avoid runtime warnings. +
  • +
  • + Fix building on Mingw/MSYS to perform file copies and deletions. + Bug #1993. +
  • +
  • + SciTE can match a wider variety of file patterns where '*' is in the middle of + the pattern and where there are multiple '*'. + A '?' matches any single character. +
  • +
  • + SciTE on Windows can execute Python scripts directly by name when on path. + Feature #1209. +
  • +
  • + SciTE on Windows Find in Files checks for cancel after every 10,000 lines read so + can be stopped on huge files. +
  • +
  • + SciTE remembers entered values in lists in more cases for find, replace and find in files. + Bug #1715. +
  • +
+

+ Release 4.0.3 +

+
    +
  • + Released 12 February 2018. +
  • +
  • + Features from C++14 and C++17 are used more often, with build files now specifying + c++17, gnu++17, c++1z, or std:c++latest (MSVC). + Requires Microsoft Visual C++ 2017.5, GCC 7, Xcode 9.2 or Clang 4.0 or newer. +
  • +
  • + SCI_CREATEDOCUMENT adds a bytes argument to allocate memory for an initial size. + SCI_CREATELOADER and SCI_CREATEDOCUMENT add a documentOption argument to + allow choosing different document capabilities. +
  • +
  • + Add SC_DOCUMENTOPTION_STYLES_NONE option to stop allocating memory for styles. +
  • +
  • + Add SCI_GETMOVEEXTENDSSELECTION to allow applications to add more + complex selection commands. +
  • +
  • + SciTE property bookmark.symbol allows choosing symbol used for bookmarks. + Feature #1208. +
  • +
  • + Improve VHDL lexer's handling of character literals and escape characters in strings. +
  • +
  • + Fix double tap word selection on Windows 10 1709 Fall Creators Update. + Bug #1983. +
  • +
  • + Fix closing autocompletion lists on Cocoa for macOS 10.13 where the window + was emptying but staying visible. + Bug #1981. +
  • +
  • + Fix drawing failure on Cocoa with animated find indicator in large files with macOS 10.12 + by disabling animation. +
  • +
  • + SciTE on GTK+ installs its desktop file as non-executable and supports the common + LDLIBS make variable. + Bug #1989, + Bug #1990. +
  • +
  • + SciTE shows correct column number when caret in virtual space. + Bug #1991. +
  • +
  • + SciTE preserves selection positions when saving with strip.trailing.spaces + and virtual space turned on. + Bug #1992. +
  • +
+

+ Release 4.0.2 +

+
    +
  • + Released 26 October 2017. +
  • +
  • + Fix HTML lexer handling of Django so that nesting a {{ }} or {% %} + Django tag inside of a {# #} Django comment does not break highlighting of rest of file +
  • +
  • + The Matlab folder now treats "while" as a fold start. + Bug #1985. +
  • +
  • + Fix failure on Cocoa with animated find indicator in large files with macOS 10.13 + by disabling animation on 10.13. +
  • +
  • + Fix Cocoa hang when Scintilla loaded from SMB share on macOS 10.13. + Bug #1979. +
  • +
+

+ Release 4.0.1 +

+
    +
  • + Released 23 October 2017. +
  • +
  • + The ILoader interface is defined in its own header ILoader.h as it is not + related to lexing so doesn't belong in ILexer.h. +
  • +
  • + The Scintilla namespace is always active for internal symbols and for the lexer interfaces + ILexer4 and IDocument. +
  • +
  • + The Baan lexer checks that matches to 3rd set of keywords are function calls and leaves as identifiers if not. + Baan lexer and folder support #context_on / #context_off preprocessor feature. +
  • +
  • + The C++ lexer improved preprocessor conformance.
    + Default value of 0 for undefined preprocessor symbols.
    + #define A is treated as #define A 1.
    + "defined A" removes "A" before replacing "defined" with value. + Bug #1966. +
  • +
  • + The Python folder treats triple-quoted f-strings like triple-quoted strings. + Bug #1977. +
  • +
  • + The SQL lexer uses sql.backslash.escapes for double quoted strings. + Bug #1968. +
  • +
  • + Minor undefined behaviour fixed. + Bug #1978. +
  • +
  • + On Cocoa, improve scrolling on macOS 10.12. + Bug #1885. +
  • +
  • + On Cocoa, fix line selection by clicking in the margin when scrolled. + Bug #1971. +
  • +
+

+ Release 4.0.0 +

+
    +
  • + Released 16 August 2017. +
  • +
  • + This is an unstable release with changes to interfaces used for lexers and platform access. + Some more changes may occur to internal and external interfaces before stability is regained with 4.1.0. +
  • +
  • + Uses C++14 features. Requires Microsoft Visual C++ 2017, GCC 7, and Clang 4.0 or newer. +
  • +
  • + Support dropped for GTK+ versions before 2.24. +
  • +
  • + The lexer interfaces ILexer and ILexerWithSubStyles, along with additional style metadata methods, were merged into ILexer4. + Most lexers will need to be updated to match the new interfaces. +
  • +
  • + The IDocumentWithLineEnd interface was merged into IDocument. +
  • +
  • + The platform layer interface has changed with unused methods removed, a new mechanism for + reporting events, removal of methods that take individual keyboard modifiers, and removal of old timer methods. +
  • +
  • + Style metadata may be retrieved from lexers that support this through the SCI_GETNAMEDSTYLES, SCI_NAMEOFSTYLE, + SCI_TAGSOFSTYLE, and SCI_DESCRIPTIONOFSTYLE APIs. +
  • +
  • + The Cocoa platform layer uses Automatic Reference Counting (ARC). +
  • +
  • + The default encoding in Scintilla is UTF-8. +
  • +
  • + An SCN_AUTOCSELECTIONCHANGE notification is sent when items are highlighted in an autocompletion or user list. +
  • +
  • + The data parameter to ILoader::AddData made const. + Bug #1955. +
  • +
  • + SciTE's embedded Lua interpreter updated to Lua 5.3. +
  • +
  • + SciTE allows event handlers to be arbitrary callables, not just functions. + Feature #1190. +
  • +
  • + SciTE allows user.shortcuts to be defined with symbolic Scintilla messages like + 'Ctrl+L|SCI_LINEDELETE|'. +
  • +
  • + The Matlab lexer treats 'end' as a number rather than a keyword when used as an index. + This also stops incorrect folding. + Bug #1951. +
  • +
  • + The Matlab folder implements "fold", "fold.comment", and "fold.compact" properties. + Bug #1965. +
  • +
  • + The Rust lexer recognizes 'usize' numeric literal suffixes. + Bug #1919. +
  • +
  • + Ensure redraw when application changes overtype mode so caret change visible even when not blinking. + Notify application with SC_UPDATE_SELECTION when overtype changed - previously + sent SC_UPDATE_CONTENT. +
  • +
  • + Fix drawing failure when in wrap mode for delete to start/end of line which + affects later lines but did not redraw them. + Also fixed drawing for wrap mode on GTK+ 2.x. + Bug #1949. +
  • +
  • + On GTK+ fix drawing problems including incorrect scrollbar redrawing and flickering of text. + Bug #1876. +
  • +
  • + On Linux, both for GTK+ and Qt, the default modifier key for rectangular selection is now Alt. + This is the same as Windows and macOS. + This was changed from Ctrl as window managers are less likely to intercept Alt+Drag for + moving windows than in the past. +
  • +
  • + On Cocoa, fix doCommandBySelector but avoid double effect of 'delete' + key. + Bug #1958. +
  • +
  • + On Qt, the updateUi signal includes the 'updated' flags. + No updateUi signal is sent for focus in events. + These changes make Qt behave more like the other platforms. +
  • +
  • + On Qt, dropping files on Scintilla now fires the SCN_URIDROPPED notification + instead of inserting text. +
  • +
  • + On Qt, focus changes send the focusChanged signal. + Bug #1957. +
  • +
  • + On Qt, mouse tracking is reenabled when the window is reshown. + Bug #1948. +
  • +
  • + On Windows, the DirectWrite modes SC_TECHNOLOGY_DIRECTWRITEDC and + SC_TECHNOLOGY_DIRECTWRITERETAIN are no longer provisional. +
  • +
  • + SciTE on macOS fixes a crash when platform-specific and platform-independent + session restoration clashed. + Bug #1960. +
  • +
  • + SciTE on GTK+ implements find.close.on.find. + Bug #1152, + Bug #1254, + Bug #1762, + Feature #849. +
  • +
+

+ Release 3.7.6 +

+
    +
  • + Released 8 August 2017. +
  • +
  • + This is the first release of the + long term branch + which avoids using features from C++14 or later in order to support older systems. +
  • +
  • + The Baan lexer correctly highlights numbers when followed by an operator. +
  • +
  • + On Cocoa, fix a bug with retrieving encoded bytes. +
  • +
+

+ Release 3.7.5 +

+
    +
  • + Released 26 May 2017. +
  • +
  • + This is the final release of SciTE 3.x. +
  • +
  • + Support dropped for Microsoft Visual C++ 2013 due to increased use of C++11 features. +
  • +
  • + Added a caret line frame as an alternative visual for highlighting the caret line. +
  • +
  • + Added "Reverse Selected Lines" feature. +
  • +
  • + SciTE adds "Select All Bookmarks" command. +
  • +
  • + SciTE adds a save.path.suggestion setting to suggest a file name when saving an + unnamed buffer. +
  • +
  • + Updated case conversion and character categories to Unicode 9. +
  • +
  • + The Baan lexer recognizes numeric literals in a more compliant manner including + hexadecimal numbers and exponentials. +
  • +
  • + The Bash lexer recognizes strings in lists in more cases. + Bug #1944. +
  • +
  • + The Fortran lexer recognizes a preprocessor line after a line continuation &. + Bug #1935. +
  • +
  • + The Fortran folder can fold comments. + Bug #1936. +
  • +
  • + The PowerShell lexer recognizes escaped quotes in strings. + Bug #1929. +
  • +
  • + The Python lexer recognizes identifiers more accurately when they include non-ASCII characters. +
  • +
  • + The Python folder treats comments at the end of the file as separate from the preceding structure. +
  • +
  • + The YAML lexer recognizes comments in more situations and styles a + "..." line like a "---" line. + Bug #1931. +
  • +
  • + Update scroll bar when annotations added, removed, or visibility changed. + Feature #1187. +
  • +
  • + Canceling modes with the Esc key preserves a rectangular selection. + Bug #1940. +
  • +
  • + Builds are made with a sorted list of lexers to be more reproducible. + Bug #1946. +
  • +
  • + On Cocoa, a leak of mouse tracking areas was fixed. +
  • +
  • + On Cocoa, the autocompletion is 4 pixels wider to avoid text truncation. +
  • +
  • + On Windows, stop drawing a focus rectangle on the autocompletion list and + raise the default list length to 9 items. +
  • +
  • + SciTE examines at most 1 MB of a file to automatically determine indentation + for indent.auto to avoid a lengthy pause when loading very large files. +
  • +
  • + SciTE user interface uses lighter colours and fewer 3D elements to match current desktop environments. +
  • +
  • + SciTE sets buffer dirty and shows message when file deleted if load.on.activate on. +
  • +
  • + SciTE on Windows Find strip Find button works in incremental no-close mode. + Bug #1926. +
  • +
+

+ Release 3.7.4 +

+
    +
  • + Released 21 March 2017. +
  • +
  • + Requires a C++11 compiler. GCC 4.8 and MSVC 2015 are supported. +
  • +
  • + Support dropped for Windows NT 4. +
  • +
  • + Accessibility support may be queried with SCI_GETACCESSIBILITY. + On GTK+, accessibility may be disabled by calling SCI_SETACCESSIBILITY. +
  • +
  • + Lexer added for "indent" language which is styled as plain text but folded by indentation level. +
  • +
  • + The Progress ABL lexer handles nested comments where comment starts or ends + are adjacent like "/*/*" or "*/*/". +
  • +
  • + In the Python lexer, improve f-string support. + Add support for multiline expressions in triple quoted f-strings. + Handle nested "()", "[]", and "{}" in f-string expressions and terminate expression colouring at ":" or "!". + End f-string if ending quote is seen in a "{}" expression. + Fix terminating single quoted f-string at EOL. + Bug #1918. +
  • +
  • + The VHDL folder folds an "entity" on the first line of the file. +
  • +
  • + For IMEs, do not clear selected text when there is no composition text to show. +
  • +
  • + Fix to crash with fold tags where line inserted at start. +
  • +
  • + Fix to stream selection mode when moving caret up or down. + Bug #1905. +
  • +
  • + Drawing fixes for fold tags include fully drawing lines and not overlapping some + drawing and ensuring edges and mark underlines are visible. +
  • +
  • + Fix Cocoa failure to display accented character chooser for European + languages by partially reverting a change made to prevent a crash with + Chinese input by special-casing the Cangjie input source. + Bug #1881. +
  • +
  • + Fix potential problems with IME on Cocoa when document contains invalid + UTF-8. +
  • +
  • + Fix crash on Cocoa with OS X 10.9 due to accessibility API not available. + Bug #1915. +
  • +
  • + Improved speed of accessibility code on GTK+ by using additional memory + as a cache. + Bug #1910. +
  • +
  • + Fix crash in accessibility code on GTK+ < 3.3.6 caused by previous bug fix. + Bug #1907. +
  • +
  • + Fix to prevent double scrolling on GTK+ with X11. + Bug #1901. +
  • +
  • + SciTE on GTK+ adds an "accessibility" property to allow disabling accessibility + on GTK+ as an optimization. +
  • +
  • + SciTE on GTK+ has changed file chooser behaviour for some actions: + overwriting an existing file shows a warning; + the default session file name "SciTE.session" is shown and a "*.session" filter is applied; + appropriate filters are applied when exporting; + the current file name is displayed in "Save As" even when that file no longer exists. +
  • +
  • + SciTE fixed a bug where, on GTK+, when the output pane had focus, menu commands + performed by mouse were sent instead to the edit pane. +
  • +
  • + SciTE on Windows 8+ further restricts the paths searched for DLLs to the application + and system directories which may prevent some binary planting attacks. +
  • +
  • + Fix failure to load Direct2D on Windows when used on old versions of Windows. + Bug #1653. +
  • +
+

+ Release 3.7.3 +

+
    +
  • + Released 19 February 2017. +
  • +
  • + Display block caret over the character at the end of a selection to be similar + to other editors. +
  • +
  • + In SciTE can choose colours for fold markers. + Feature #1172. +
  • +
  • + In SciTE can hide buffer numbers in tabs. + Feature #1173. +
  • +
  • + The Diff lexer recognizes deleted lines that start with "--- ". +
  • +
  • + The Lua lexer requires the first line to start with "#!" to be treated as a shebang comment, + not just "#". + Bug #1900. +
  • +
  • + The Matlab lexer requires block comment start and end to be alone on a line. + Bug #1902. +
  • +
  • + The Python lexer supports f-strings with new styles, allows Unicode identifiers, + and no longer allows @1 to be a decorator. + Bug #1848. +
  • +
  • + Fix folding inconsistency when fold header added above a folded part. + Avoid unnecessary unfolding when a deletion does not include a line end. + Bug #1896. +
  • +
  • + Fix finalization crash on Cocoa. + Bug #1909. +
  • +
  • + SciTE on GTK+ can have a wide divider between the panes with the + split.wide property. +
  • +
  • + Fix display of autocompletion lists and calltips on GTK+ 3.22 on Wayland. + Newer APIs used on GTK+ 3.22 as older APIs were deprecated. +
  • +
  • + Fix crash in accessibility code on GTK+ due to signal receipt after destruction. + Bug #1907. +
  • +
  • + Make trackpad scrolling work on Wayland. + Bug #1901. +
  • +
+

+ Release 3.7.2 +

+
    +
  • + Released 30 December 2016. +
  • +
  • + Minimize redrawing for SCI_SETSELECTIONN* APIs. + Bug #1888. +
  • +
  • + Use more precision to allow selecting individual lines in files with + more than 16.7 million lines. +
  • +
  • + For Qt 5, define QT_WS_MAC or QT_WS_X11 on those platforms. + Bug #1887. +
  • +
  • + For Cocoa, fix crash on view destruction with macOS 10.12.2. + Bug #1891. +
  • +
  • + Fix crash on GTK+ <3.8 due to incorrect lifetime of accessibility object. + More accurate reporting of attribute ranges and deletion lengths for accessibility. +
  • +
  • + In SciTE, if a Lua script causes a Scintilla failure exception, display error + message in output pane instead of exiting. + Bug #1773. +
  • +
+

+ Release 3.7.1 +

+
    +
  • + Released 4 December 2016. +
  • +
  • + The Scintilla namespace is no longer applied to struct definitions in Scintilla.h even + when SCI_NAMESPACE defined. + Client code should not define SCI_NAMESPACE. +
  • +
  • + Structure names in Scintilla.h without prefixes are deprecated and will now only + be usable with INCLUDE_DEPRECATED_FEATURES defined.
    + Use the newer names with the "Sci_" prefix:
    + CharacterRange → Sci_CharacterRange
    + TextRange → Sci_TextRange
    + TextToFind → Sci_TextToFind
    + RangeToFormat → Sci_RangeToFormat
    + NotifyHeader → Sci_NotifyHeader +
  • +
  • + Previously deprecated features SC_CP_DBCS, SCI_SETUSEPALETTE. and SCI_GETUSEPALETTE + have been removed and can no longer be used in client code. +
  • +
  • + Single phase drawing SC_PHASES_ONE is deprecated along with the + SCI_SETTWOPHASEDRAW and SCI_GETTWOPHASEDRAW messages. +
  • +
  • + Accessibility support allowing screen readers to work added on GTK+ and Cocoa. +
  • +
  • + Textual tags may be displayed to the right on folded lines with SCI_TOGGLEFOLDSHOWTEXT. + This is commonly something like "{ ... }" or "<tr>...</tr>". + It is displayed with the STYLE_FOLDDISPLAYTEXT style and may have a box drawn around it + with SCI_FOLDDISPLAYTEXTSETSTYLE. +
  • +
  • + A mouse right-click over the margin may send an SCN_MARGINRIGHTCLICK event. + This only occurs when popup menus are turned off. + SCI_USEPOPUP now has three states: SC_POPUP_NEVER, SC_POPUP_ALL, or SC_POPUP_TEXT. +
  • +
  • + INDIC_POINT and INDIC_POINTCHARACTER indicators added to display small arrows + underneath positions or characters. +
  • +
  • + Added alternate appearance for visible tabs which looks like a horizontal line. + Controlled with SCI_SETTABDRAWMODE. + Feature #1165. +
  • +
  • + On Cocoa, a modulemap file is included to allow Scintilla to be treated as a module. + This makes it easier to use Scintilla from the Swift language. +
  • +
  • + Baan folder accommodates sections and lexer fixes definition of SCE_BAAN_FUNCDEF. +
  • +
  • + EDIFACT lexer and folder added. + Feature #1166. +
  • +
  • + JSON folder fixed where it didn't resume folding with the correct fold level. +
  • +
  • + Matlab folder based on syntax instead of indentation so more accurate. + Bug #1692. +
  • +
  • + YAML lexer fixed style of references and keywords when followed by a comment. + Bug #1872. +
  • +
  • + Margin click to select line now clears rectangular and additional selections. +
  • +
  • + Fixed a NULL access bug on GTK+ where the scrollbars could be used during destruction. + Bug #1873. +
  • +
  • + A potential bug on GTK+ fixed where asynchronous clipboard could be delivered after its + target Scintilla instance was destroyed. +
  • +
  • + Cocoa IME made more compliant with documented behaviour to avoid bugs that caused + huge allocations. + Bug #1881. +
  • +
  • + On Win32 fix EM_SETSEL to match Microsoft documentation.. + Bug #1886. +
  • +
  • + SciTE on GTK+ allows localizing tool bar tool tips. + Feature #1167. +
  • +
  • + SciTE on Windows restores focus to edit pane after closing user strip. +
  • +
  • + SciTE measures files larger that 2 GB which allows it to refuse to open huge files more consistently + and to show better warning messages. +
  • +
+

+ Release 3.7.0 +

+
    +
  • + Released 16 October 2016. +
  • +
  • + Word selection, navigation, and manipulation is now performed on characters instead of bytes + leading to more natural behaviour for multi-byte encodings like UTF-8. + For UTF-8 characters 0x80 and above, classification into word; punctuation; space; or line-end + is based on the Unicode general category of the character and is not customizable. + Bug #1832. +
  • +
  • + Two enums changed in Scintilla.iface which may lead to changed bindings. + There were 2 FontQuality enums and the first is now PhasesDraw. + The prefix for FoldAction was SC_FOLDACTION and is now SC_FOLDACTION_ + which is similar to other enums. + These changes do not affect the standard C/C++ binding. +
  • +
  • + EDGE_MULTILINE and SCI_MULTIEDGEADDLINE added to allow displaying multiple + vertical edges simultaneously. +
  • +
  • + The number of margins can be changed with SCI_SETMARGINS. +
  • +
  • + Margin type SC_MARGIN_COLOUR added so that the application may + choose any colour for a margin with SCI_SETMARGINBACKN. +
  • +
  • + On Win32, mouse wheel scrolling can be restricted to only occur when the mouse is + within the window. +
  • +
  • + The WordList class in lexlib used by lexers adds an InListAbridged method for + matching keywords that have particular prefixes and/or suffixes. +
  • +
  • + The Baan lexer was changed significantly with more lexical states, keyword sets, + and support for abridged keywords. +
  • +
  • + The CoffeeScript lexer styles interpolated code in strings. + Bug #1865. +
  • +
  • + The Progress lexer "progress" has been replaced with a new lexer "abl" + (Advanced Business Language) + with a different set of lexical states and more functionality. + The lexical state prefix has changed from SCE_4GL_ to SCE_ABL_. + Feature #1143. +
  • +
  • + The PowerShell lexer understands the grave accent escape character. + Bug #1868. +
  • +
  • + The YAML lexer recognizes inline comments. + Bug #1660. +
  • +
  • + SciTE on Windows can retain coloured selection when inactive with + selection.always.visible property. +
  • +
  • + SciTE on Windows adds a state to close.on.find to close the find strip when + a match is found. +
  • +
  • + Fix caret position after left or right movement with rectangular selection. + Bug #1861. +
  • +
  • + In SciTE, optional prefix argument added to scite.ConstantName method. + Bug #1860. +
  • +
  • + On Cocoa, include ILexer.h in the public headers of the framework. + Bug #1855. +
  • +
  • + On Cocoa, allow subclass of SCIContentView to set cursor. + Bug #1863. +
  • +
  • + On Cocoa, recognize the numeric keypad '+', '-', and '/' keys as + SCK_ADD, SCK_SUBTRACT, and SCK_DIVIDE. + Bug #1867. +
  • +
  • + On GTK+ 3.21+ fix incorrect font size in auto-completion list. + Bug #1859. +
  • +
  • + Fix SciTE crash when command.mode ends with comma. + Bug #1857. +
  • +
  • + SciTE on Windows has a full size toolbar icon for "Close". +
  • +
+

+ Release 3.6.7 +

+
    +
  • + Released 4 September 2016. +
  • +
  • + C++11 range-based for loops used in SciTE so GCC 4.6 is now the minimum supported version. +
  • +
  • + SC_CHARSET_DEFAULT now means code page 1252 on Windows unless a code page is set. + This prevents unexpected behaviour and crashes on East Asian systems where default locales are commonly DBCS. + Projects which want to default to DBCS code pages in East Asian locales should set the code page and + character set explicitly. +
  • +
  • + SCVS_NOWRAPLINESTART option stops left arrow from wrapping to the previous line. + Most commonly wanted when virtual space is used. + Bug #1648. +
  • +
  • + The C++ lexer can fold on #else and #elif with the fold.cpp.preprocessor.at.else property. + Bug #210. +
  • +
  • + The errorlist lexer detects warnings from Visual C++ which do not contain line numbers. +
  • +
  • + The HTML lexer no longer treats "<?" inside a string in a script as potentially starting an XML document. + Bug #767. +
  • +
  • + The HTML lexer fixes a problem resuming at a script start where the starting state continued + past where it should. + Bug #1849. +
  • +
  • + When inserting spaces for virtual space and the position is in indentation and tabs are enabled + for indentation then use tabs. + Bug #1850. +
  • +
  • + Fix fold expand when some child text not styled. + Caused by fixes for Bug #1799. + Bug #1842. +
  • +
  • + Fix key binding bug on Cocoa for control+. + Bug #1854. +
  • +
  • + Fix scroll bar size warnings on GTK+ caused by #1831. + Bug #1851. +
  • +
  • + Small fixes for GTK+ makefile. + Bug #1844. + Bug #1845. + Bug #1846. +
  • +
  • + Fix SciTE indentation after code like "void function () {}". +
  • +
  • + Fix SciTE global regex replace of "^" with something which missed the line after empty + lines with LF line ends. + Bug #1839. +
  • +
  • + Fix SciTE on GTK+ 3.20 bug where toggle buttons on find and replace strips + did not show active state. + Bug #1853. +
  • +
+

+ Release 3.6.6 +

+
    +
  • + Released 24 May 2016. +
  • +
  • + C++ 11 <regex> support built by default. Can be disabled by defining NO_CXX11_REGEX. +
  • +
  • + SciTE_USERHOME environment variable allows separate location for writeable properties files. + Feature #965. +
  • +
  • + GObject introspection supports notify and command events. +
  • +
  • + The Progress lexer now allows comments preceded by a tab. +
  • +
  • + Scripts reading Scintilla.iface file include comments for enu and lex definitions. + Bug #1829. +
  • +
  • + Fix crashes on GTK+ if idle work active when destroyed. + Bug #1827. +
  • +
  • + Fixed bugs when used on GTK+ 3.20. + Bug #1825. + Bug #1831. +
  • +
  • + Fix SciTE search field background with dark theme on GTK+ 2.x. + Bug #1826. +
  • +
  • + Fixed bug on Win32 that allowed resizing autocompletion from bottom when it was + located above the caret. +
  • +
  • + On Win32, when using a screen reader and selecting text using Shift+Arrow, + fix bug when scrolling made the caret stay at the same screen location + so the screen reader did not speak the added or removed selection. +
  • +
+

+ Release 3.6.5 +

+
    +
  • + Released 26 April 2016. +
  • +
  • + JSON lexer added. + Feature #1140. +
  • +
  • + The C++ lexer fixes a bug with multi-line strings with line continuation where the string style + overflowed after an edit. + Bug #1824. +
  • +
  • + The Python lexer treats '@' as an operator except when it is the first visible character on a line. + This is for Python 3.5. +
  • +
  • + The Rust lexer allows '?' as an operator. + Feature #1146. +
  • +
  • + Doubled size of compiled regex buffer. + Bug #1822. +
  • +
  • + For GTK+, the Super modifier key can be used in key bindings. + Feature #1142. +
  • +
  • + For GTK+, fix some crashes when using multiple threads. +
  • +
  • + Platform layer font cache removed on GTK+ as platform-independent caches are used. + This avoids the use of thread locking and initialization of threads so any GTK+ + applications that rely on Scintilla initializing threads will have to do that themselves. +
  • +
  • + SciTE bug fixed with exported HTML where extra line shown. + Bug #1816. +
  • +
  • + SciTE on Windows fixes bugs with pop-up menus in the find and replace strips. + For the replace strip, menu choices change the state. + For the find strip, menu choices are reflected in the appearance of their corresponding buttons. +
  • +
  • + SciTE on Windows on high DPI displays fixes the height of edit boxes in user strips. +
  • +
+

+ Release 3.6.4 +

+
    +
  • + Released 13 March 2016. +
  • +
  • + SciTE allows setting the autocompletion type separator character. +
  • +
  • + The C++ folder folds code on '(' and ')' to allow multi-line calls to be folded. + Feature #1138. +
  • +
  • + For the HTML lexer, limit the extent of Mako line comments to finish before + the line end characters. +
  • +
  • + Folds unfolded when two fold regions are merged by either deleting an intervening line + or changing its fold level by adding characters. + This was fixed both in Scintilla and in SciTE's equivalent code. + Bug #1799.
    +
  • +
  • + The Progress lexer supports hexadecimal numeric literals, + single-line comments, abbreviated keywords and + extends nested comments to unlimited levels. +
  • +
  • + Ruby lexer treats alternate hash key syntax "key:" as a symbol. + Bug #1810. +
  • +
  • + Rust lexer handles bracketed Unicode string escapes like "\u{123abc}". + Bug #1809. +
  • +
  • + For GTK+ on Windows fix 64-bit build which was broken in 3.6.3. +
  • +
  • + For Qt, release builds have assertions turned off. +
  • +
  • + For Qt on Windows, fix compilation failure for Qt 4.x. +
  • +
  • + IME target range displayed on Qt for OS X. +
  • +
  • + On Windows, make clipboard operations more robust by retrying OpenClipboard if it fails + as this may occur when another application has opened the clipboard. +
  • +
  • + On Windows back out change that removed use of def file to ensure + Scintilla_DirectFunction exported without name mangling. + Bug #1813. +
  • +
  • + On GTK+ and Qt over Win32 in Korean fix bug caused by last release's word input change. +
  • +
  • + For SciTE, more descriptive error messages are displayed when there are problems loading the + Lua startup script. + Feature #1139. +
  • +
+

+ Release 3.6.3 +

+
    +
  • + Released 18 January 2016. +
  • +
  • + Allow painting without first styling all visible text then styling in the background + using idle-time. This helps performance when scrolling down in very large documents. + Can also incrementally style after the visible area to the end of the document so that + the document is already styled when the user scrolls to it. +
  • +
  • + Support GObject introspection on GTK+. +
  • +
  • + SciTE supports pasting to each selection with the selection.multipaste setting. + Feature #1123. +
  • +
  • + SciTE can optionally display a read-only indicator on tabs and in the Buffers menu. +
  • +
  • + Bash lexer flags incomplete here doc delimiters as syntax errors. + Bug #1789.
    + Support added for using '#' in non-comment ways as is possible with zsh. + Bug #1794.
    + Recognize more characters as here-doc delimiters. + Bug #1778. +
  • +
  • + Errorlist lexer highlights warning messages from the Microsoft linker. +
  • +
  • + Errorlist lexer fixes bug with final line in escape sequence recognition mode. +
  • +
  • + Lua lexer includes '&' and '|' bitwise operators for Lua 5.3. + Bug #1790. +
  • +
  • + Perl lexer updated for Perl 5.20 and 5.22.
    + Allow '_' for subroutine prototypes. + Bug #1791.
    + Double-diamond operator <<>>.
    + Hexadecimal floating point literals.
    + Repetition in list assignment. + Bug #1793.
    + Highlight changed subroutine prototype syntax for Perl 5.20. + Bug #1797.
    + Fix module ::-syntax when special characters such as 'x' are used.
    + Added ' and " detection as prefix chars for x repetition operator. + Bug #1800. +
  • +
  • + Visual Prolog lexer recognizes numbers more accurately and allows non-ASCII verbatim + quoting characters. + Feature #1130. +
  • +
  • + Send SCN_UPDATEUI with SC_UPDATE_SELECTION when the application changes multiple + selection. +
  • +
  • + Expand folded areas before deleting fold header line. + Bug #1796. +
  • +
  • + Treat Unicode line ends like common line ends when maintaining fold state. +
  • +
  • + Highlight whole run for hover indicator when wrapped. + Bug #1784. +
  • +
  • + On Cocoa, fix crash when autocompletion list closed during scroll bounce-back. + Bug #1788. +
  • +
  • + On Windows, fix non-BMP input through WM_CHAR and allow WM_UNICHAR to work + with non-BMP characters and on non-Unicode documents. + Bug #1779. +
  • +
  • + On Windows using DirectWrite, for ligatures and other character clusters, + display caret and selections part-way through clusters so that the caret doesn't stick + to the end of the cluster making it easier to understand editing actions. +
  • +
  • + On Windows, Scintilla no longer uses a .DEF file during linking as it duplicates + source code directives. +
  • +
  • + On GTK+ and Qt, Korean input by word fixed. +
  • +
  • + On GTK+, Qt, and Win32 block IME input when document is read-only or any selected text + is protected. +
  • +
  • + On GTK+ on OS X, fix warning during destruction. + Bug #1777. +
  • +
  • + Fix SciTE crashes when using LPEG lexers. +
  • +
+

+ Release 3.6.2 +

+
    +
  • + Released 6 November 2015. +
  • +
  • + Whitespace may be made visible just in indentation. +
  • +
  • + Whitespace dots are centred when larger than 1 pixel. +
  • +
  • + The Scintilla framework on Cocoa now contains version numbers. +
  • +
  • + SciTE's standard properties collect values from all active .properties file to produce the Language menu + and the file types pull-down in the File open dialog. +
  • +
  • + The single executable version of SciTE, Sc1, uses 'module' statements within its embedded + properties. This makes it act more like the full distribution allowing languages to be turned on + and off by setting imports.include and imports.exclude. + The default imports.exclude property adds eiffel, erlang, ps, and pov so these languages are + turned off by default. +
  • +
  • + SciTE adds an output.blank.margin.left property to allow setting the output pane + margin to a different width than the edit pane. +
  • +
  • + CoffeeScript lexer highlights ranges correctly. + Bug #1765. +
  • +
  • + Markdown lexer treats line starts consistently to always highlight *foo* or similar at line start. + Bug #1766. +
  • +
  • + Optimize marker redrawing by only drawing affected lines when markers shown in the text. +
  • +
  • + On Cocoa, timers and idling now work in modal dialogs. This also stops some crashes. +
  • +
  • + On Cocoa, fix crashes when deleting a ScintillaView. These crashes could occur when scrolling + at the time the ScintillaView was deleted although there may have been other cases. +
  • +
  • + On GTK+ 2.x, fix height of lines in autocompletion lists. + Bug #1774. +
  • +
  • + Fix bug with SCI_LINEENDDISPLAY where the caret moved to the next document line instead of the + end of the display line. + Bug #1772. +
  • +
  • + Report error (SC_STATUS_FAILURE) when negative length passed to SCI_SETSTYLING. + Bug #1768. +
  • +
  • + When SC_MARK_UNDERLINE is not assigned to a margin, stop drawing the whole line. +
  • +
  • + When reverting an untitled document in SciTE, just clear it with no message about a file. + Bug #1764. +
  • +
  • + SciTE on GTK+ allows use of Ctrl+A (Select All) inside find and replace strips. + Bug #1769. +
  • +
+

+ Release 3.6.1 +

+
    +
  • + Released 15 September 2015. +
  • +
  • + The oldest version of GTK+ supported now is 2.18 and for glib it is 2.22. +
  • +
  • + On GTK+, SC_CHARSET_OEM866 added to allow editing Russian files encoded in code page 866. + Feature #1019. +
  • +
  • + On Windows, reconversion is performed when requested by the IME. +
  • +
  • + CoffeeScript lexer adds lexical class for instance properties and fixes some cases of regex highlighting. + Bug #1749. +
  • +
  • + The errorlist lexer understands some ANSI escape sequences to change foreground colour and intensity. + This is sufficient to colour diagnostic output from gcc and clang when -fdiagnostics-color set. +
  • +
  • + The errorlist lexer allows the line number to be 0 in GCC errors as some tools report whole file + errors as line 0. +
  • +
  • + MySql lexer fixes empty comments /**/ so the comment state does not continue. +
  • +
  • + VHDL folder supports "protected" keyword. +
  • +
  • + Treat CRLF line end as two characters in SCI_COUNTCHARACTERS. + Bug #1757. +
  • +
  • + On GTK+ 3.x, fix height of lines in autocompletion lists to match the font. + Switch from deprecated style calls to CSS styling. + Removed setting list colours on GTK+ 3.16+ as no longer appears needed. +
  • +
  • + On GTK+, avoid "Invalid rectangle passed" warning messages by never reporting the client + rectangle with a negative width or height. + Bug #1743. +
  • +
  • + On Cocoa, copy Sci_Position.h into the framework so clients can build. +
  • +
  • + On Cocoa fix bug with drag and drop that could lead to crashes. + Bug #1751. +
  • +
  • + Fix SciTE disk exhaustion bug by reporting failures when writing files. + Bug #1760. +
  • +
  • + Fix find strip in SciTE on Windows XP to be visible. +
  • +
  • + SciTE on Windows changes the way it detects that a tool has finished executing to ensure all output data + from the process is read. +
  • +
  • + SciTE on Windows improves the time taken to read output from tools that produce a large amount + of output by a factor of around 10. +
  • +
  • + On GTK+ the keyboard command for View | End of Line was changed to Ctrl+Shift+N + to avoid clash with Search | Selection Add Next. + Bug #1750. +
  • +
+

+ Release 3.6.0 +

+
    +
  • + Released 3 August 2015. +
  • +
  • + External interfaces use the Sci_Position and Sci_PositionU typedefs instead of int and unsigned int + to allow for changes to a 64-bit interface on 64-bit platforms in the future. + Applications and external lexers should start using the new type names so that + they will be compatible when the 64-bit change occurs. + There is also Sci_PositionCR (long) for use in the Sci_CharacterRange struct which will + also eventually become 64-bit. +
  • +
  • + Multiple selection now works over more key commands. + The new multiple-selection handling commands include horizontal movement and selection commands, + line up and down movement and selection commands, word and line deletion commands, and + line end insertion. + This change in behaviours is conditional on setting the SCI_SETADDITIONALSELECTIONTYPING property. +
  • +
  • + Autocompletion lists send an SCN_AUTOCCOMPLETED notification after the text has been inserted. + Feature #1109. +
  • +
  • + The case mode style attribute can now be SC_CASE_CAMEL. +
  • +
  • + The Python lexer supports substyles for identifiers. +
  • +
  • + SciTE adds support for substyles. +
  • +
  • + SciTE's Export as RTF and Copy as RTF commands support UTF-8. +
  • +
  • + SciTE can display autocompletion on all IME input with ime.autocomplete property. +
  • +
  • + SciTE properties files now discard trailing white space on variable names. +
  • +
  • + Calling SCI_SETIDENTIFIERS resets styling to ensure any added identifier are highlighted. +
  • +
  • + Avoid candidate box randomly popping up away from edit pane with (especially + Japanese) IME input. +
  • +
  • + On Cocoa fix problems with positioning of autocompletion lists near screen edge + or under dock. Cancel autocompletion when window moved. + Bug #1740. +
  • +
  • + Fix drawing problem when control characters are in a hidden style as they then + have a zero width rectangle to draw but modify that rectangle in a way that + clears some pixels. +
  • +
  • + Report error when attempt to resize buffer to more than 2GB with SC_STATUS_FAILURE. +
  • +
  • + Fix bug on GTK+ with scroll bars leaking. + Bug #1742. +
  • +
  • + LexOthers.cxx file split into one file per lexer: LexBatch, LexDiff, + LexErrorList, LexMake, LexNull, and LexProps. +
  • +
  • + SciTE exporters handle styles > 127 correctly now. +
  • +
  • + SciTE on Windows can scale window element sizes based on the system DPI setting. +
  • +
  • + SciTE implements find.in.files.close.on.find on all platforms, not just Windows. +
  • +
+

+ Release 3.5.7 +

+
    +
  • + Released 20 June 2015. +
  • +
  • + Added SCI_MULTIPLESELECTADDNEXT to add the next occurrence of the main selection within the + target to the set of selections as main. If the current selection is empty then select word around caret. + SCI_MULTIPLESELECTADDEACH adds each occurrence of the main selection within the + target to the set of selections. +
  • +
  • + SciTE adds "Selection Add Next" and "Selection Add Each" commands to the Search menu. +
  • +
  • + Added SCI_ISRANGEWORD to determine if the parameters are at the start and end of a word. +
  • +
  • + Added SCI_TARGETWHOLEDOCUMENT to set the target to the whole document. +
  • +
  • + Verilog lexer recognizes protected regions and the folder folds protected regions. +
  • +
  • + A performance problem with markers when deleting many lines was fixed. + Bug #1733. +
  • +
  • + On Cocoa fix crash when ScintillaView destroyed if no autocompletion ever displayed. + Bug #1728. +
  • +
  • + On Cocoa fix crash in drag and drop. +
  • +
  • + On GTK+ 3.4+, when there are both horizontal and vertical scrollbars, draw the lower-right corner + so that it does not appear black when text selected. + Bug #1611. +
  • +
  • + Fixed most calls deprecated in GTK+ 3.16. Does not fix style override calls + as they are more complex. +
  • +
  • + SciTE on GTK+ 3.x uses a different technique for highlighting the search strip when there is + no match which is more compatible with future and past versions and different themes. +
  • +
+

+ Release 3.5.6 +

+
    +
  • + Released 26 May 2015. +
  • +
  • + On Qt, use fractional positioning calls and avoid rounding to ensure consistency. +
  • +
  • + SCI_TARGETASUTF8 and SCI_ENCODEDFROMUTF8 implemented on + Win32 as well as GTK+ and Cocoa. +
  • +
  • + C++ lexer fixes empty backquoted string. + Bug #1711. +
  • +
  • + C++ lexer fixes #undef directive. + Bug #1719. +
  • +
  • + Fortran folder fixes handling of "selecttype" and "selectcase". + Bug #1724. +
  • +
  • + Verilog folder folds interface definitions. +
  • +
  • + VHDL folder folds units declarations and fixes a case insensitivity bug with not treating "IS" the same as "is". +
  • +
  • + Fix bug when drawing text margins in buffered mode which would use default + encoding instead of chosen encoding. + Bug #1703. +
  • +
  • + Fix bug with Korean Hanja conversions in DBCS encoding on Windows. +
  • +
  • + Fix for reading a UTF-16 file in SciTE where a non-BMP character is split over a read buffer boundary. + Bug #1710. +
  • +
  • + Fix bug on GTK+ 2.x for Windows where there was an ABI difference between + compiler version. + Bug #1726. +
  • +
  • + Fix undo bug on Cocoa that could lose data.. +
  • +
  • + Fix link error on Windows when SCI_NAMESPACE used. +
  • +
  • + Fix exporting from SciTE when using Scintillua for lexing. +
  • +
  • + SciTE does not report twice that a search string can not be found when "Replace" pressed. + Bug #1716. +
  • +
  • + SciTE on GTK+ 3.x disables arrow in search combo when no entries. + Bug #1717. +
  • +
+

+ Release 3.5.5 +

+
    +
  • + Released 17 April 2015. +
  • +
  • + Scintilla on Windows is now always a wide character window so SCI_SETKEYSUNICODE has no effect + and SCI_GETKEYSUNICODE always returns true. These APIs are deprecated and should not be called. +
  • +
  • + The wxWidgets-specific ascent member of Font has been removed which breaks + compatibility with current wxStyledTextCtrl. + Bug #1682. +
  • +
  • + IME on Qt supports multiple carets and behaves more like other platforms. +
  • +
  • + Always use inline IME on GTK+ for Korean. +
  • +
  • + SQL lexer fixes handling of '+' and '-' in numbers so the '-' in '1-1' is seen as an operator and for + '1--comment' the comment is recognized. +
  • +
  • + TCL lexer reverts change to string handling. + Bug #1642. +
  • +
  • + Verilog lexer fixes bugs with macro styling. + Verilog folder fixes bugs with `end completing an `if* instead of `endif and fold.at.else, and implements + folding at preprocessor `else. +
  • +
  • + VHDL lexer supports extended identifiers. +
  • +
  • + Fix bug on Cocoa where the calltip would display incorrectly when + switching calltips and the new calltip required a taller window. +
  • +
  • + Fix leak on Cocoa with autocompletion lists. + Bug #1706. +
  • +
  • + Fix potential crash on Cocoa with drag and drop. + Bug #1709. +
  • +
  • + Fix bug on Windows when compiling with MinGW-w64 which caused text to not be drawn + when in wrap mode. + Bug #1705. +
  • +
  • + Fix SciTE bug with missing file open filters and add hex to excluded set of properties files so that its + settings don't appear. + Bug #1707. +
  • +
  • + Fix SciTE bug where files without extensions like "makefile" were not highlighted correctly. +
  • +
+

+ Release 3.5.4 +

+
    +
  • + Released 8 March 2015. +
  • +
  • + Indicators may have a different colour and style when the mouse is over them or the caret is moved into them. +
  • +
  • + An indicator may display in a large variety of colours with the SC_INDICFLAG_VALUEFORE + flag taking the colour from the indicator's value, which may differ for every character, instead of its + foreground colour attribute. +
  • +
  • + On Cocoa, additional IME methods implemented so that more commands are enabled. + For Japanese: Reverse Conversion, Convert to Related Character, and Search Similar Kanji + can now be performed. + The global definition hotkey Command+Control+D and the equivalent three finger tap gesture + can be used. +
  • +
  • + Minimum version of Qt supported is now 4.8 due to the use of QElapsedTimer::nsecsElapsed. +
  • +
  • + On Windows, for Korean, the VK_HANJA key is implemented to choose Hanja for Hangul and + to convert from Hanja to Hangul. +
  • +
  • + C++ lexer adds lexer.cpp.verbatim.strings.allow.escapes option that allows verbatim (@") strings + to contain escape sequences. This should remain off (0) for C# and be turned on (1) for Objective C. +
  • +
  • + Rust lexer accepts new 'is'/'us' integer suffixes instead of 'i'/'u'. + Bug #1098. +
  • +
  • + Ruby folder can fold multiline comments. + Bug #1697. +
  • +
  • + SQL lexer fixes a bug with the q-quote operator. +
  • +
  • + TCL lexer fixes a bug with some strings. + Bug #1642. +
  • +
  • + Verilog lexer handles escaped identifiers that begin with \ and end with space like \reset* . + Verilog folder fixes one bug with inconsistent folding when fold.comment is on and another + with typedef class statements creating a fold point, expecting an endclass statement. +
  • +
  • + VHDL folder fixes hang in folding when document starts with "entity". +
  • +
  • + Add new indicators INDIC_COMPOSITIONTHIN, INDIC_FULLBOX, and INDIC_TEXTFORE. + INDIC_COMPOSITIONTHIN is a thin underline that mimics the appearance of non-target segments in OS X IME. + INDIC_FULLBOX is similar to INDIC_STRAIGHTBOX but covers the entire character area which means that + indicators with this style on contiguous lines may touch. INDIC_TEXTFORE changes the text foreground colour. +
  • +
  • + Fix adaptive scrolling speed for GTK+ on OS X with GTK Quartz backend (as opposed to X11 backend). + Bug #1696. +
  • +
  • + Fix position of autocompletion and calltips on Cocoa when there were two screens stacked vertically. +
  • +
  • + Fix crash in SciTE when saving large files in background when closing application. + Bug #1691. +
  • +
  • + Fix decoding of MSVC warnings in SciTE so that files in the C:\Program Files (x86)\ directory can be opened. + This is a common location of system include files. +
  • +
  • + Fix compilation failure of C++11 <regex> on Windows using gcc. +
  • +
+

+ Release 3.5.3 +

+
    +
  • + Released 20 January 2015. +
  • +
  • + Support removed for Windows 95, 98, and ME. +
  • +
  • + Lexers added for Motorola S-Record files, Intel hex files, and Tektronix extended hex files with folding for Intel hex files. + Feature #1091. + Feature #1093. + Feature #1095. + Feature #1096. +
  • +
  • + C++ folder allows folding on square brackets '['. + Feature #1087. +
  • +
  • + Shell lexer fixes three issues with here-documents. + Bug #1672. +
  • +
  • + Verilog lexer highlights doc comment keywords; has separate styles for input, output, and inout ports + (lexer.verilog.portstyling); fixes a bug in highlighting numbers; can treat upper-case identifiers as + keywords (lexer.verilog.allupperkeywords); and can use different styles for code that is inactive due + to preprocessor commands (lexer.verilog.track.preprocessor, lexer.verilog.update.preprocessor). +
  • +
  • + When the calltip window is taller than the Scintilla window, leave it in a + position that avoids overlapping the Scintilla text. +
  • +
  • + When a text margin is displayed, for annotation lines, use the background colour of the base line. +
  • +
  • + On Windows GDI, assume font names are encoded in UTF-8. This matches the Direct2D code path. +
  • +
  • + Fix paste for GTK+ on OS X. + Bug #1677. +
  • +
  • + Reverted a fix on Qt where Qt 5.3 has returned to the behaviour of 4.x. + Bug #1575. +
  • +
  • + When the mouse is on the line between margin and text changed to treat as within text. + This makes the PLAT_CURSES character cell platform work better. +
  • +
  • + Fix a crash in SciTE when the command line is just "-close:". + Bug #1675. +
  • +
  • + Fix unexpected dialog in SciTE on Windows when the command line has a quoted filename then ends with a space. + Bug #1673. +
  • +
  • + On Windows and GTK+, use indicators for inline IME. +
  • +
  • + SciTE shuts down quicker when there is no user-written OnClose function and no directors are attached. +
  • +
+

+ Release 3.5.2 +

+
    +
  • + Released 2 December 2014. +
  • +
  • + For OS X Cocoa switch C++ runtime to libc++ to enable use of features that will never + be added to libstdc++ including those part of C++11. + Scintilla will now run only on OS X 10.7 or later and only in 64-bit mode. +
  • +
  • + Include support for using C++11 <regex> for regular expression searches. + Enabling this requires rebuilding Scintilla with a non-default option. + This is a provisional feature and may change API before being made permanent. +
  • +
  • + Allocate indicators used for Input Method Editors after 31 which was the previous limit of indicators to + ensure no clash between the use of indicators for IME and for the application. +
  • +
  • + ANNOTATION_INDENTED added which is similar to ANNOTATION_BOXED in terms of positioning + but does not show a border. + Feature #1086. +
  • +
  • + Allow platform overrides for drawing tab arrows, wrap markers, and line markers. + Size of double click detection area is a variable. + These enable better visuals and behaviour for PLAT_CURSES as it is character cell based. +
  • +
  • + CoffeeScript lexer fixes "/*" to not be a comment. + Bug #1420. +
  • +
  • + VHDL folder fixes "block" keyword. + Bug #1664. +
  • +
  • + Prevent caret blinking when holding down Delete key. + Bug #1657. +
  • +
  • + On Windows, allow right click selection in popup menu. + Feature #1080. +
  • +
  • + On Windows, only call ShowCaret in GDI mode as it interferes with caret drawing when using Direct2D. + Bug #1643. +
  • +
  • + On Windows, another DirectWrite mode SC_TECHNOLOGY_DIRECTWRITEDC added + which may avoid drawing failures in some circumstances by drawing into a GDI DC. + This feature is provisional and may be changed or removed if a better solution is found. +
  • +
  • + On Windows, avoid processing mouse move events where the mouse has not moved as these can + cause unexpected dwell start notifications. + Bug #1670. +
  • +
  • + For GTK+ on Windows, avoid extra space when pasting from external application. +
  • +
  • + On GTK+ 2.x allow Scintilla to be used inside tool tips by changing when preedit window created. + Bug #1662. +
  • +
  • + Support MinGW compilation under Linux. + Feature #1077. +
  • +
+

+ Release 3.5.1 +

+
    +
  • + Released 30 September 2014. +
  • +
  • + BibTeX lexer added. + Feature #1071. +
  • +
  • + SQL lexer supports the q-quote operator as SCE_SQL_QOPERATOR(24). +
  • +
  • + VHDL lexer supports block comments. + Bug #1527. +
  • +
  • + VHDL folder fixes case where "component" used before name. + Bug #613. +
  • +
  • + Restore fractional pixel tab positioning which was truncated to whole pixels in 3.5.0. + Bug #1652. +
  • +
  • + Allow choice between windowed and inline IME on some platforms. +
  • +
  • + On GTK+ cache autocomplete window to avoid platform bug where windows + were sometimes lost. + Bug #1649. +
  • +
  • + On GTK+ size autocomplete window more accurately. +
  • +
  • + On Windows only unregister windows classes registered. + Bug #1639. +
  • +
  • + On Windows another DirectWrite mode SC_TECHNOLOGY_DIRECTWRITERETAIN added + which may avoid drawing failures on some cards and drivers. + This feature is provisional and may be changed or removed if a better solution is found. +
  • +
  • + On Windows support the Visual Studio 2010+ clipboard format that indicates a line copy. + Bug #1636. +
  • +
  • + SciTE session files remember the scroll position. +
  • +
+

+ Release 3.5.0 +

+
    +
  • + Released 13 August 2014. +
  • +
  • + Text may share space vertically so that extreme ascenders and descenders are + not cut off by calling SCI_SETPHASESDRAW(SC_PHASES_MULTIPLE). +
  • +
  • + Separate timers are used for each type of periodic activity and they are turned on and off + as required. This saves power as there are fewer wake ups. + On recent releases of OS X Cocoa and Windows, coalescing timers are used to further + save power. + Bug #1086. + Bug #1532. +
  • +
  • + Explicit tab stops may be set for each line. +
  • +
  • + On Windows and GTK+, when using Korean input methods, IME composition is moved from a + separate window into the Scintilla window. +
  • +
  • + SciTE adds a "Clean" command to the "Tools" menu which is meant to be bound to a command like + "make clean". +
  • +
  • + Lexer added for Windows registry files. +
  • +
  • + HTML lexer fixes a crash with SGML after a Mako comment. + Bug #1622. +
  • +
  • + KiXtart lexer adds a block comment state. + Feature #1053. +
  • +
  • + Matlab lexer fixes transpose operations like "X{1}'". + Bug #1629. +
  • +
  • + Ruby lexer fixes bugs with the syntax of symbols including allowing a symbol to end with '?'. + Bug #1627. +
  • +
  • + Rust lexer supports byte string literals, naked CR can be escaped in strings, and files starting with + "#![" are not treated as starting with a hashbang comment. + Feature #1063. +
  • +
  • + Bug fixed where style data was stale when deleting a rectangular selection. +
  • +
  • + Bug fixed where annotations disappeared when SCI_CLEARDOCUMENTSTYLE called. +
  • +
  • + Bug fixed where selection not redrawn after SCI_DELWORDRIGHT. + Bug #1633. +
  • +
  • + Change the function prototypes to be complete for functions exported as "C". + Bug #1618. +
  • +
  • + Fix a memory leak on GTK+ with autocompletion lists. + Bug #1638. +
  • +
  • + On GTK+, use the full character width for the overstrike caret for multibyte characters. +
  • +
  • + On Qt, set list icon size to largest icon. Add padding on OS X. + Bug #1634. +
  • +
  • + On Qt, fix building on FreeBSD 9.2. + Bug #1635. +
  • +
  • + On Qt, add a get_character method on the document. + Feature #1064. +
  • +
  • + On Qt, add SCI_* for methods to ScintillaConstants.py. + Feature #1065. +
  • +
  • + SciTE on GTK+ crash fixed with Insert Abbreviation command. +
  • +
  • + For SciTE with read-only files and are.you.sure=0 reenable choice to save to another + location when using Save or Close commands. +
  • +
  • + Fix SciTE bug where toggle bookmark did not work after multiple lines with bookmarks merged. + Bug #1617. +
  • +
+

+ Release 3.4.4 +

+
    +
  • + Released 3 July 2014. +
  • +
  • + Style byte indicators removed. They were deprecated in 2007. Standard indicators should be used instead. + Some elements used by lexers no longer take number of bits or mask arguments so lexers may need to be + updated for LexAccessor::StartAt, LexAccessor::SetFlags (removed), LexerModule::LexerModule. +
  • +
  • + When multiple selections are active, autocompletion text may be inserted at each selection with new + SCI_AUTOCSETMULTI method. +
  • +
  • + C++ lexer fixes crash for "#define x(". + Bug #1614. +
  • +
  • + C++ lexer fixes raw string recognition so that R"xxx(blah)xxx" is styled as SCE_C_STRINGRAW. +
  • +
  • + The Postscript lexer no longer marks token edges with indicators as this used style byte indicators. +
  • +
  • + The Scriptol lexer no longer displays indicators for poor indentation as this used style byte indicators. +
  • +
  • + TCL lexer fixes names of keyword sets. + Bug #1615. +
  • +
  • + Shell lexer fixes fold matching problem caused by "<<<". + Bug #1605. +
  • +
  • + Fix bug where indicators were not removed when fold highlighting on. + Bug #1604. +
  • +
  • + Fix bug on Cocoa where emoji were treated as being zero width. +
  • +
  • + Fix crash on GTK+ with Ubuntu 12.04 and overlay scroll bars. +
  • +
  • + Avoid creating a Cairo context when measuring text on GTK+ as future versions of GTK+ + may prohibit calling gdk_cairo_create except inside drawing handlers. This prohibition may + be required on Wayland. +
  • +
  • + On Cocoa, the registerNotifyCallback method is now marked as deprecated so client code that + uses it will display an error message. + Client code should use the delegate mechanism or subclassing instead. + The method will be removed in the next version. +
  • +
  • + On Cocoa, package Scintilla more in compliance with platform conventions. + Only publish public headers in the framework headers directory. + Only define the Scintilla namespace in Scintilla.h when compiling as C++. + Use the Cocoa NS_ENUM and NS_OPTIONS macros for exposed enumerations. + Hide internal methods from public headers. + These changes are aimed towards publishing Scintilla as a module which will allow it to + be used from the Swift programming language, although more changes will be needed here. +
  • +
  • + Fix crash in SciTE when stream comment performed at line end. + Bug #1610. +
  • +
  • + For SciTE on Windows, display error message when common dialogs fail. + Bug #156. +
  • +
  • + For SciTE on GTK+ fix bug with initialization of toggle buttons in find and replace strips. + Bug #1612. +
  • +
+

+ Release 3.4.3 +

+
    +
  • + Released 27 May 2014. +
  • +
  • + Fix hangs and crashes in DLL at shutdown on Windows when using Direct2D. +
  • +
+

+ Release 3.4.2 +

+
    +
  • + Released 22 May 2014. +
  • +
  • + Insertions can be filtered or modified by calling SCI_CHANGEINSERTION inside a handler for + SC_MOD_INSERTCHECK. +
  • +
  • + DMIS lexer added. DMIS is a language for coordinate measuring machines. + Feature #1049. +
  • +
  • + Line state may be displayed in the line number margin to aid in debugging lexing and folding with + SC_FOLDFLAG_LINESTATE (128). +
  • +
  • + C++ lexer understands more preprocessor statements. #if defined SYMBOL is understood. + Some macros with arguments can be understood and these may be predefined in keyword set 4 + (keywords5 for SciTE) + with syntax similar to CHECKVERSION(x)=(x<3). + Feature #1051. +
  • +
  • + C++ lexer can highlight task marker keywords in comments as SCE_C_TASKMARKER. +
  • +
  • + C++ lexer can optionally highlight escape sequences in strings as SCE_C_ESCAPESEQUENCE. +
  • +
  • + C++ lexer supports Go back quoted raw string literals with lexer.cpp.backquoted.strings option. + Feature #1047. +
  • +
  • + SciTE performs word and search match highlighting as an idle task to improve interactivity + and allow use of these features on large files. +
  • +
  • + Bug fixed on Cocoa where previous caret lines were visible. + Bug #1593. +
  • +
  • + Bug fixed where caret remained invisible when period set to 0. + Bug #1592. +
  • +
  • + Fixed display flashing when scrolling with GTK+ 3.10. + Bug #1567. +
  • +
  • + Fixed calls and constants deprecated in GTK+ 3.10. +
  • +
  • + Fixed bug on Windows where WM_GETTEXT did not provide data in UTF-16 for Unicode window. + Bug #685. +
  • +
  • + For SciTE, protect access to variables used by threads with a mutex to prevent data races. +
  • +
  • + For SciTE on GTK+ fix thread object leaks. + Display the version of GTK+ compiled against in the about box. +
  • +
  • + For SciTE on GTK+ 3.10, fix the size of the tab bar's content and use + freedesktop.org standard icon names where possible. +
  • +
  • + For SciTE on Windows, fix bug where invoking help resubmitted the + running program. + Bug #272. +
  • +
  • + SciTE's highlight current word feature no longer matches the selection when it contains space. +
  • +
  • + For building SciTE in Visual C++, the win\SciTE.vcxproj project file should be used. + The boundscheck directory and its project and solution files have been removed. +
  • +
+

+ Release 3.4.1 +

+
    +
  • + Released 1 April 2014. +
  • +
  • + Display Unicode line ends as [LS], [PS], and [NEL] blobs. +
  • +
  • + Bug fixed where cursor down failed on wrapped lines. + Bug #1585. +
  • +
  • + Caret positioning changed a little to appear inside characters less often by + rounding the caret position to the pixel grid instead of truncating. + Bug #1588. +
  • +
  • + Bug fixed where automatic indentation wrong when caret in virtual space. + Bug #1586. +
  • +
  • + Bug fixed on Windows where WM_LBUTTONDBLCLK was no longer sent to window. + Bug #1587. +
  • +
  • + Bug fixed with SciTE on Windows XP where black stripes appeared inside the find and + replace strips. +
  • +
  • + Crash fixed in SciTE with recursive properties files. + Bug #1507. +
  • +
  • + Bug fixed with SciTE where Ctrl+E before an unmatched end brace jumps to file start. + Bug #315. +
  • +
  • + Fixed scrolling on Cocoa to avoid display glitches and be smoother. +
  • +
  • + Fixed crash on Cocoa when character composition used when autocompletion list active. +
  • +
+

+ Release 3.4.0 +

+
    +
  • + Released 22 March 2014. +
  • +
  • + The Unicode line ends and substyles features added as provisional in 3.2.5 are now finalized. + There are now no provisional features. +
  • +
  • + Added wrap mode SC_WRAP_WHITESPACE which only wraps on whitespace, not on style changes. +
  • +
  • + SciTE find and replace strips can perform incremental searching and temporary highlighting of all + matches with the find.strip.incremental, replace.strip.incremental, and find.indicator.incremental settings. +
  • +
  • + SciTE default settings changed to use strips for find and replace and to draw with Direct2D and + DirectWrite on Windows. +
  • +
  • + SciTE on Windows scales image buttons on the find and replace strips to match the current system scale factor. +
  • +
  • + Additional assembler lexer variant As(SCLEX_AS) for Unix assembly code which uses '#' for comments and + ';' to separate statements. +
  • +
  • + Fix Coffeescript lexer for keyword style extending past end of word. + Also fixes styling 0...myArray.length all as a number. + Bug #1583. +
  • +
  • + Fix crashes and other bugs in Fortran folder by removing folding of do-label constructs. +
  • +
  • + Deleting a whole line deletes the annotations on that line instead of the annotations on the next line. + Bug #1577. +
  • +
  • + Changed position of tall calltips to prefer lower half of screen to cut off end instead of start. +
  • +
  • + Fix Qt bug where double click treated as triple click. + Bug #1575. +
  • +
  • + On Qt, selecting an item in an autocompletion list that is not currently visible positions it at the top. +
  • +
  • + Fix bug on Windows when resizing autocompletion list with only short strings caused the list to move. +
  • +
  • + On Cocoa reduce scrollable height by one line to fix bugs with moving caret + up or down. +
  • +
  • + On Cocoa fix calltips which did not appear when they were created in an off-screen position. +
  • +
+

+ Release 3.3.9 +

+
    +
  • + Released 31 January 2014. +
  • +
  • + Fix 3.3.8 bug where external lexers became inaccessible. + Bug #1574. +
  • +
+

+ Release 3.3.8 +

+
    +
  • + Released 28 January 2014. +
  • +
  • + DropSelectionN API added to drop a selection from a multiple selection. +
  • +
  • + CallTipSetPosStart API added to change the position at which backspacing removes the calltip. +
  • +
  • + SC_MARK_BOOKMARK marker symbol added which looks like bookmark ribbons used in + book reading applications. +
  • +
  • + Basic lexer highlights hex, octal, and binary numbers in FreeBASIC which use the prefixes + &h, &o and &b respectively. + Feature #1041. +
  • +
  • + C++ lexer fixes bug where keyword followed immediately by quoted string continued + keyword style. + Bug #1564. +
  • +
  • + Matlab lexer treats '!' differently for Matlab and Octave languages. + Bug #1571. +
  • +
  • + Rust lexer improved with nested comments, more compliant doc-comment detection, + octal literals, NUL characters treated as valid, and highlighting of raw string literals and float literals fixed. + Feature #1038. + Bug #1570. +
  • +
  • + On Qt expose the EOLMode on the document object. +
  • +
  • + Fix hotspot clicking where area was off by half a character width. + Bug #1562. +
  • +
  • + Tweaked scroll positioning by either 2 pixels or 1 pixel when caret is at left or right of view + to ensure caret is inside visible area. +
  • +
  • + Send SCN_UPDATEUI with SC_UPDATE_SELECTION for Shift+Tab inside text. +
  • +
  • + On Windows update the system caret position when scrolling to help screen readers + see the scroll quickly. +
  • +
  • + On Cocoa, GTK+, and Windows/Direct2D draw circles more accurately so that + circular folding margin markers appear circular, of consistent size, and centred. + Make SC_MARK_ARROWS drawing more even. + Fix corners of SC_MARK_ROUNDRECT with Direct2D to be similar to other platforms. +
  • +
  • + SciTE uses a bookmark ribbon symbol for bookmarks as it scales better to higher resolutions + than the previous blue gem bitmap. +
  • +
  • + SciTE will change the width of margins while running when the margin.width and fold.margin.width + properties are changed. +
  • +
  • + SciTE on Windows can display a larger tool bar with the toolbar.large property. +
  • +
  • + SciTE displays a warning message when asked to open a directory. + Bug #1568. +
  • +
+

+ Release 3.3.7 +

+
    +
  • + Released 12 December 2013. +
  • +
  • + Lexer added for DMAP language. + Feature #1026. +
  • +
  • + Basic lexer supports multiline comments in FreeBASIC. + Feature #1023. +
  • +
  • + Bash lexer allows '#' inside words.. + Bug #1553. +
  • +
  • + C++ lexer recognizes C++11 user-defined literals and applies lexical class SCE_C_USERLITERAL. +
  • +
  • + C++ lexer allows single quote characters as digit separators in numeric literals like 123'456 as this is + included in C++14. +
  • +
  • + C++ lexer fixes bug with #include statements without " or > terminating filename. + Bug #1538. +
  • +
  • + C++ lexer fixes split of Doxygen keywords @code{.fileExtension} and @param[in,out]. + Bug #1551. +
  • +
  • + C++ lexer styles Doxygen keywords at end of document. +
  • +
  • + Cmake lexer fixes bug with empty comments. + Bug #1550. +
  • +
  • + Fortran folder improved. Treats "else" as fold header. + Feature #962. +
  • +
  • + Fix bug with adjacent instances of the same indicator with different values where only the first was drawn. + Bug #1560. +
  • +
  • + For DirectWrite, use the GDI ClearType gamma value for SC_EFF_QUALITY_LCD_OPTIMIZED as + this results in text that is similar in colour intensity to GDI. + For the duller default DirectWrite ClearType text appearance, use SC_EFF_QUALITY_DEFAULT. + Feature #887. +
  • +
  • + Fix another problem with drawing on Windows with Direct2D when returning from lock screen. + The whole window is redrawn as just redrawing the initially required area left other areas black. +
  • +
  • + When scroll width is tracked, take width of annotation lines into account. +
  • +
  • + For Cocoa on OS X 10.9, responsive scrolling is supported. +
  • +
  • + On Cocoa, apply font quality setting to line numbers. + Bug #1544. +
  • +
  • + On Cocoa, clicking in margin now sets focus. + Bug #1542. +
  • +
  • + On Cocoa, correct cursor displayed in margin after showing dialog. +
  • +
  • + On Cocoa, multipaste mode now works. + Bug #1541. +
  • +
  • + On GTK+, chain up to superclass finalize so that all finalization is performed. + Bug #1549. +
  • +
  • + On GTK+, fix horizontal scroll bar range to not be double the needed width. + Bug #1546. +
  • +
  • + On OS X GTK+, report control key as SCI_META for mouse down events. +
  • +
  • + On Qt, bug fixed with drawing of scrollbars, where previous contents were not drawn over with some + themes. +
  • +
  • + On Qt, bug fixed with finding monitor rectangle which could lead to autocomplete showing at wrong location. +
  • +
  • + SciTE fix for multiple message boxes when failing to save a file with save.on.deactivate. + Bug #1540. +
  • +
  • + SciTE on GTK+ fixes SIGCHLD handling so that Lua scripts can determine the exit status of processes + they start. + Bug #1557. +
  • +
  • + SciTE on Windows XP fixes bad display of find and replace values when using strips. +
  • +
+

+ Release 3.3.6 +

+
    +
  • + Released 15 October 2013. +
  • +
  • + Added functions to help convert between substyles and base styles and between secondary and primary styles. + SCI_GETSTYLEFROMSUBSTYLE finds the base style of substyles. + Can be used to treat all substyles of a style equivalent to that style. + SCI_GETPRIMARYSTYLEFROMSTYLE finds the primary style of secondary styles. + StyleFromSubStyle and PrimaryStyleFromStyle methods were added to ILexerWithSubStyles so each lexer can implement these. +
  • +
  • + Lexer added for Rust language. + Feature #1024. +
  • +
  • + Avoid false matches in errorlist lexer which is used for the SciTE output pane + by stricter checking of ctags lines. +
  • +
  • + Perl lexer fixes bugs with multi-byte characters, including in HEREDOCs and PODs. + Bug #1528. +
  • +
  • + SQL folder folds 'create view' statements. + Feature #1020. +
  • +
  • + Visual Prolog lexer updated with better support for string literals and Unicode. + Feature #1025. +
  • +
  • + For SCI_SETIDENTIFIERS, \t, \r, and \n are allowed as well as space between identifiers. + Bug #1521. +
  • +
  • + Gaining and losing focus is now reported as a notification with the code set to SCN_FOCUSIN + or SCN_FOCUSOUT. + This allows clients to uniformly use notifications instead of commands. + Since there is no longer a need for commands they will be deprecated in a future version. + Clients should switch any code that currently uses SCEN_SETFOCUS or SCEN_KILLFOCUS. +
  • +
  • + On Cocoa, clients should use the delegate mechanism or subclass ScintillaView in preference + to registerNotifyCallback: which will be deprecated in the future. +
  • +
  • + On Cocoa, the ScintillaView.h header hides internal implementation details from Platform.h and ScintillaCocoa.h. + InnerView was renamed to SCIContentView and MarginView was renamed to SCIMarginView. + dealloc removed from @interface. +
  • +
  • + On Cocoa, clients may customize SCIContentView by subclassing both SCIContentView and ScintillaView + and implementing the contentViewClass class method on the ScintillaView subclass to return the class of + the SCIContentView subclass. +
  • +
  • + On Cocoa, fixed appearance of alpha rectangles to use specified alpha and colour for outline as well as corner size. + This makes INDIC_STRAIGHTBOX and INDIC_ROUNDBOX look correct. +
  • +
  • + On Cocoa, memory leak fixed for MarginView. +
  • +
  • + On Cocoa, make drag and drop work when destination view is empty. + Bug #1534. +
  • +
  • + On Cocoa, drag image fixed when view scrolled. +
  • +
  • + On Cocoa, SCI_POSITIONFROMPOINTCLOSE fixed when view scrolled. + Feature #1021. +
  • +
  • + On Cocoa, don't send selection change notification when scrolling. + Bug #1522. +
  • +
  • + On Qt, turn off idle events on destruction to prevent repeatedly calling idle. +
  • +
  • + Qt bindings in ScintillaEdit changed to use signed first parameter. +
  • +
  • + Compilation errors fixed on Windows and GTK+ with SCI_NAMESPACE. +
  • +
  • + On Windows, building with gcc will check if Direct2D headers are available and enable Direct2D if they are. +
  • +
  • + Avoid attempts to redraw empty areas when lexing beyond the currently visible lines. +
  • +
  • + Control more attributes of indicators in SciTE with find.mark.indicator and highlight.current.word.indicator + properties. +
  • +
  • + Fix SciTE bug with buffers becoming read-only. + Bug #1525. +
  • +
  • + Fix linking SciTE on non-Linux Unix systems with GNU toolchain by linking to libdl. + Bug #1523. +
  • +
  • + On Windows, SciTE's Incremental Search displays match failures by changing the background colour + instead of not adding the character that caused failure. +
  • +
  • + Fix SciTE on GTK+ 3.x incremental search to change foreground colour when no match as + changing background colour is difficult. +
  • +
+

+ Release 3.3.5 +

+
    +
  • + Released 31 August 2013. +
  • +
  • + Characters may be represented by strings. + In Unicode mode C1 control characters are represented by their mnemonics. +
  • +
  • + Added SCI_POSITIONRELATIVE to optimize navigation by character. +
  • +
  • + Option to allow mouse selection to switch to rectangular by pressing Alt after start of gesture. + Feature #1007. +
  • +
  • + Lexer added for KVIrc script. + Feature #1008. +
  • +
  • + Bash lexer fixed quoted HereDoc delimiters. + Bug #1500. +
  • +
  • + MS SQL lexer fixed ';' to appear as an operator. + Bug #1509. +
  • +
  • + Structured Text lexer fixed styling of enumeration members. + Bug #1508. +
  • +
  • + Fixed bug with horizontal caret position when margin changed. + Bug #1512. +
  • +
  • + Fixed bug on Cocoa where coordinates were relative to text subview instead of whole view. +
  • +
  • + Ensure selection redrawn correctly in two cases. + When switching from stream to rectangular selection with Alt+Shift+Up. + When reducing the range of an additional selection by moving mouse up. + Feature #1007. +
  • +
  • + Copy and paste of rectangular selections compatible with Borland Delphi IDE on Windows. + Feature #1002. + Bug #1513. +
  • +
  • + Initialize extended styles to the default style. +
  • +
  • + On Windows, fix painting on an explicit HDC when first paint attempt abandoned. +
  • +
  • + Qt bindings in ScintillaEdit made to work on 64-bit Unix systems. +
  • +
  • + Easier access to printing on Qt with formatRange method. +
  • +
  • + Fixed SciTE failure to save initial buffer in single buffer mode. + Bug #1339. +
  • +
  • + Fixed compilation problem with Visual C++ in non-English locales. + Bug #1506. +
  • +
  • + Disable Direct2D when compiling with MinGW gcc on Windows because of changes in the recent MinGW release. +
  • +
  • + SciTE crash fixed for negative line.margin.width. + Bug #1504. +
  • +
  • + SciTE fix for infinite dialog boxes when failing to automatically save a file. + Bug #1503. +
  • +
  • + SciTE settings buffered.draw, two.phase.draw, and technology are applied to the + output pane as well as the edit pane. +
  • +
+

+ Release 3.3.4 +

+
    +
  • + Released 19 July 2013. +
  • +
  • + Handling of UTF-8 and DBCS text in lexers improved with methods ForwardBytes and + GetRelativeCharacter added to StyleContext. + Bug #1483. +
  • +
  • + For Unicode text, case-insensitive searching and making text upper or lower case is now + compliant with Unicode standards on all platforms and is much faster for non-ASCII characters. +
  • +
  • + A CategoriseCharacter function was added to return the Unicode general category of a character + which can be useful in lexers. +
  • +
  • + On Cocoa, the LCD Optimized font quality level turns font smoothing on. +
  • +
  • + SciTE 'immediate' subsystem added to allow scripts that work while tools are executed. +
  • +
  • + Font quality exposed in SciTE as font.quality setting. +
  • +
  • + On Cocoa, message:... methods simplify direct access to Scintilla and avoid call layers.. +
  • +
  • + A68K lexer updated. +
  • +
  • + CoffeeScript lexer fixes a bug with comment blocks. + Bug #1495 +
  • +
  • + ECL lexer regular expression code fixed. + Bug #1491. +
  • +
  • + errorlist lexer only recognizes Perl diagnostics when there is a filename between + "at" and "line". Had been triggering for MSVC errors containing "at line". +
  • +
  • + Haskell lexer fixed to avoid unnecessary full redraws. + Don't highlight CPP inside comments when styling.within.preprocessor is on. + Bug #1459. +
  • +
  • + Lua lexer fixes bug in labels with UTF-8 text. + Bug #1483. +
  • +
  • + Perl lexer fixes bug in string interpolation with UTF-8 text. + Bug #1483. +
  • +
  • + Fixed bugs with case conversion when the result was longer or shorter than the original text. + Could access past end of string potentially crashing. + Selection now updated to result length. +
  • +
  • + Fixed bug where data being inserted and removed was not being reported in + notification messages. Bug was introduced in 3.3.2. +
  • +
  • + Word wrap bug fixed where the last line could be shown twice. +
  • +
  • + Word wrap bug fixed for lines wrapping too short on Windows and GTK+. +
  • +
  • + Word wrap performance improved. +
  • +
  • + Minor memory leak fixed. + Bug #1487. +
  • +
  • + On Cocoa, fixed insertText: method which was broken when implementing a newer protocol. +
  • +
  • + On Cocoa, fixed a crash when performing string folding for bytes that do not represent a character + in the current encoding. +
  • +
  • + On Qt, fixed layout problem when QApplication construction delayed. +
  • +
  • + On Qt, find_text reports failure with -1 as first element of return value. +
  • +
  • + Fixed SciTE on GTK+ bug where a tool command could be performed using the keyboard while one was + already running leading to confusion and crashes. + Bug #1486. +
  • +
  • + Fixed SciTE bug in Copy as RTF which was limited to first 32 styles. + Bug #1011. +
  • +
  • + Fixed SciTE on Windows user strip height when the system text scaling factor is 125% or 150%. +
  • +
  • + Compile time checks for Digital Mars C++ removed. +
  • +
  • + Visual C++ 2013 supported. + Bug #1492. +
  • +
  • + Python scripts used for building and maintenance improved and moved into scripts directory. +
  • +
  • + Testing scripts now work on Linux using Qt and PySide. +
  • +
  • + Tk platform defined. + Implementation for Tk will be available separately from main Scintilla distribution. +
  • +
+

+ Release 3.3.3 +

+
    +
  • + Released 2 June 2013. +
  • +
  • + Lexer and folder added for Structured Text language. + Feature #959. +
  • +
  • + Out of bounds access fixed for GTK+. + Bug #1480. +
  • +
  • + Crash fixed for GTK+ on Windows paste. +
  • +
  • + Bug fixed with incorrect event copying on GTK+ 3.x. + Bug #1481. +
  • +
  • + Bug fixed with right to left locales, like Hebrew, on GTK+. + Bug #1477. +
  • +
  • + Bug fixed with undo grouping of tab and backtab commands. + Bug #1478. +
  • +
+

+ Release 3.3.2 +

+
    +
  • + Released 22 May 2013. +
  • +
  • + Basic implementations of common folding methods added to Scintilla to make it + easier for containers to implement folding. +
  • +
  • + Add indicator INDIC_COMPOSITIONTHICK, a thick low underline, to mimic an + appearance used for Asian language input composition. +
  • +
  • + On Cocoa, implement font quality setting. + Feature #988. +
  • +
  • + On Cocoa, implement automatic enabling of commands and added clear command. + Feature #987. +
  • +
  • + C++ lexer adds style for preprocessor doc comment. + Feature #990. +
  • +
  • + Haskell lexer and folder improved. Separate mode for literate Haskell "literatehaskell" SCLEX_LITERATEHASKELL. + Bug #1459 . +
  • +
  • + LaTeX lexer bug fixed for Unicode character following '\'. + Bug #1468 . +
  • +
  • + PowerShell lexer recognizes here strings and doccomment keywords. + #region folding added. + Feature #985. +
  • +
  • + Fix multi-typing when two carets are located in virtual space on one line so that spaces + are preserved. +
  • +
  • + Fixes to input composition on Cocoa and implementation of accented character input through + press and hold. Set selection correctly so that changes to pieces of composition text are easier to perform. + Restore undo collection after a sequence of composition actions. + Composition popups appear near input. +
  • +
  • + Fix lexer problem where no line end was seen at end of document. +
  • +
  • + Fix crash on Cocoa when view deallocated. + Bug #1466. +
  • +
  • + Fix Qt window positioning to not assume the top right of a monitor is at 0, 0. +
  • +
  • + Fix Qt to not track mouse when widget is hidden. +
  • +
  • + Qt now supports Qt 5.0. + Bug #1448. +
  • +
  • + Fix drawing on Windows with Direct2D when returning from lock screen. + The render target had to be recreated and an area would be black since the drawing was not retried. +
  • +
  • + Fix display of DBCS documents on Windows Direct2D/DirectWrite with default character set. +
  • +
  • + For SciTE on Windows, fixed most-recently-used menu when files opened through check.if.already.opened. +
  • +
  • + In SciTE, do not call OnSave twice when files saved asynchronously. +
  • +
  • + Scintilla no longer builds with Visual C++ 6.0. +
  • +
+

+ Release 3.3.1 +

+
    +
  • + Released 11 April 2013. +
  • +
  • + Autocompletion lists can now appear in priority order or be sorted by Scintilla. + Feature #981. +
  • +
  • + Most lexers now lex an extra NUL byte at the end of the + document which makes it more likely they will classify keywords at document end correctly. + Bug #574, + Bug #588. +
  • +
  • + Haskell lexer improved in several ways. + Bug #1459. +
  • +
  • + Matlab/Octave lexer recognizes block comments and ... comments. + Bug #1414. +
  • +
  • + Ruby lexer crash fixed with keyword at start of document. +
  • +
  • + The PLAT_NCURSES platform now called PLAT_CURSES as may work on other implementations. +
  • +
  • + Bug on Cocoa fixed where input composition with multiple selection or virtual space selection + could make undo stop working. +
  • +
  • + Direct2D/DirectWrite mode on Windows now displays documents in non-Latin1 8-bit encodings correctly. +
  • +
  • + Character positioning corrected in Direct2D/DirectWrite mode on Windows to avoid text moving and cutting off + lower parts of characters. +
  • +
  • + Position of calltip and autocompletion lists fixed on Cocoa. +
  • +
  • + While regular expression search in DBCS text is still not working, matching partial characters is now avoided + by moving end of match to end of character. +
  • +
+

+ Release 3.3.0 +

+
    +
  • + Released 30 March 2013. +
  • +
  • + Overlay scrollers and kinetic scrolling implemented on Cocoa. +
  • +
  • + To improve display smoothness, styling and UI Update notifications will, when possible, be performed in + a high-priority idle task on Cocoa instead of during painting. + Performing these jobs inside painting can cause paints to be abandoned and a new paint scheduled. + On GTK+, the high-priority idle task is used in more cases. +
  • +
  • + SCI_SCROLLRANGE added to scroll the view to display a range of text. + If the whole range can not be displayed, priority is given to one end. +
  • +
  • + C++ lexer no longer recognizes raw (R"") strings when the first character after " + is invalid. + Bug #1454. +
  • +
  • + HTML lexer recognizes JavaScript RegEx literals in more contexts. + Bug #1412. +
  • +
  • + Fixed automatic display of folded text when return pressed at end of fold header and + first folded line was blank. + Bug #1455. +
  • +
  • + SCI_VISIBLEFROMDOCLINE fixed to never return a line beyond the document end. +
  • +
  • + SCI_LINESCROLL fixed for a negative column offset. + Bug #1450. +
  • +
  • + On GTK+, fix tab markers so visible if indent markers are visible. + Bug #1453. +
  • +
+

+ Release 3.2.5 +

+
    +
  • + Released 26 February 2013. +
  • +
  • + To allow cooperation between different uses of extended (beyond 255) styles they should be allocated + using SCI_ALLOCATEEXTENDEDSTYLES. +
  • +
  • + For Unicode documents, lexers that use StyleContext will retrieve whole characters + instead of bytes. + LexAccessor provides a LineEnd method which can be a more efficient way to + handle line ends and can enable Unicode line ends. +
  • +
  • + The C++ lexer understands the #undef directive when determining preprocessor definitions. + Feature #978. +
  • +
  • + The errorlist lexer recognizes gcc include path diagnostics that appear before an error. +
  • +
  • + Folding implemented for GetText (PO) translation language. + Bug #1437. +
  • +
  • + HTML lexer does not interrupt comment style for processing instructions. + Bug #1447. +
  • +
  • + Fix SciTE forgetting caret x-position when switching documents. + Bug #1442. +
  • +
  • + Fixed bug where vertical scrollbar thumb appeared at beginning of document when + scrollbar shown. + Bug #1446. +
  • +
  • + Fixed brace-highlighting bug on OS X 10.8 where matching brace is on a different line. +
  • +
  • + Provisional features + are new features that may change or be removed if they cause problems but should become + permanent if they work well. + For this release Unicode line ends and + substyles + are provisional features. +
  • +
+

+ Release 3.2.4 +

+
    +
  • + Released 17 January 2013. +
  • +
  • + Caret line highlight can optionally remain visible when window does not have focus. + Feature #964. +
  • +
  • + Delegate mechanism for notifications added on Cocoa. +
  • +
  • + NUL characters in selection are copied to clipboard as spaces to avoid truncating + at the NUL. + Bug #1289. +
  • +
  • + C++ lexer fixes problem with showing inactive sections when preprocessor lines contain trailing comment. + Bug #1413. +
  • +
  • + C++ lexer fixes problem with JavaScript regular expressions with '/' in character ranges. + Bug #1415. +
  • +
  • + LaTeX folder added. + Feature #970. +
  • +
  • + LaTeX lexer improves styling of math environments. + Feature #970. +
  • +
  • + MySQL lexer implements hidden commands. +
  • +
  • + Only produce a single undo step when autocompleting a single word. + Bug #1421. +
  • +
  • + Fixed crash when printing lines longer than 8000 characters. + Bug #1430. +
  • +
  • + Fixed problem in character movement extends selection mode where reversing + direction collapsed the selection. +
  • +
  • + Memory issues fixed on Cocoa, involving object ownership, + lifetime of timers, and images held by the info bar. + Bug #1436. +
  • +
  • + Cocoa key binding for Alt+Delete changed to delete previous word to be more compatible with + platform standards. +
  • +
  • + Fixed crash on Cocoa with scrollbar when there is no scrolling possible. + Bug #1416. +
  • +
  • + On Cocoa with retina display fixed positioning of autocompletion lists. +
  • +
  • + Fixed SciTE on Windows failure to run a batch file with a name containing a space by + quoting the path in the properties file. + Bug #1423. +
  • +
  • + Fixed scaling bug when printing on GTK+. + Bug #1427. +
  • +
  • + SciTE on GTK toolbar.detachable feature removed. +
  • +
  • + Fixed some background saving bugs in SciTE. + Bug #1366. + Bug #1339. +
  • +
+

+ Release 3.2.3 +

+
    +
  • + Released 21 October 2012. +
  • +
  • + Improve speed when performing multiple searches. +
  • +
  • + SciTE adds definition of PLAT_UNIX for both PLAT_GTK and PLAT_MAC to allow consolidation of + settings valid on all Unix variants. +
  • +
  • + Signal autoCompleteCancelled added on Qt. +
  • +
  • + Bash lexer supports nested delimiter pairs. + Feature #3569352. + Bug #1515556. + Bug #3008483. + Bug #3512208. + Bug #3515392. +
  • +
  • + For C/C++, recognize exponent in floating point hexadecimal literals. + Bug #3576454. +
  • +
  • + For C #include statements, do not treat // in the path as a comment. + Bug #3519260. +
  • +
  • + Lexer for GetText translations (PO) improved with additional styles and single instance limitation fixed. +
  • +
  • + Ruby for loop folding fixed. + Bug #3240902. + Bug #3567391. +
  • +
  • + Ruby recognition of here-doc after class or instance variable fixed. + Bug #3567809. +
  • +
  • + SQL folding of loop and case fixed. + Bug #3567905. +
  • +
  • + SQL folding of case with assignment fixed. + Bug #3571820. +
  • +
  • + Fix hang when removing all characters from indicator at end of document. +
  • +
  • + Fix failure of \xhh in regular expression search for values greater than 0x79. +
  • +
  • + On Cocoa on OS X 10.8, fix inverted drawing of find indicator. +
  • +
  • + On Cocoa, fix double drawing when horizontal scroll range small and user swipes horizontally. +
  • +
  • + On Cocoa, remove incorrect setting of save point when reading information through 'string' and 'selectedString'. +
  • +
  • + On Cocoa, fix incorrect memory management of infoBar. +
  • +
  • + On GTK+ 3 Ubuntu, fix crash when drawing margin. +
  • +
  • + On ncurses, fix excessive spacing with italics line end. +
  • +
  • + On Windows, search for D2D1.DLL and DWRITE.DLL in system directory to avoid loading from earlier + in path where could be planted by malware. +
  • +
+

+ Release 3.2.2 +

+
    +
  • + Released 31 August 2012. +
  • +
  • + Retina display support for Cocoa. Text size fixed. + Scale factor for images implemented so they can be displayed in high definition. +
  • +
  • + Implement INDIC_SQUIGGLEPIXMAP as a faster version of INDIC_SQUIGGLE. + Avoid poor drawing at right of INDIC_SQUIGGLE. + Align INDIC_DOTBOX to pixel grid for full intensity. +
  • +
  • + Implement SCI_GETSELECTIONEMPTY API. + Bug #3543121. +
  • +
  • + Added SCI_VCHOMEDISPLAY and SCI_VCHOMEDISPLAYEXTEND key commands. + Feature #3561433. +
  • +
  • + Allow specifying SciTE Find in Files directory with find.in.directory property. + Feature #3558594. +
  • +
  • + Override SciTE global strip.trailing.spaces with strip.trailing.spaces by pattern files. + Feature #3556320. +
  • +
  • + Fix long XML script tag handling in XML lexer. + Bug #3534190. +
  • +
  • + Fix rectangular selection range after backspace. + Bug #3543097. +
  • +
  • + Send SCN_UPDATEUI with SC_UPDATE_SELECTION for backspace in virtual space. + Bug #3543121. +
  • +
  • + Avoid problems when calltip highlight range is negative. + Bug #3545938. +
  • +
  • + On Cocoa, fix image drawing code so that image is not accessed after being freed + and is drawn in the correct location. +
  • +
  • + On Cocoa, limit horizontal touch scrolling to existing established width. +
  • +
  • + On Cocoa, decrease sensitivity of pinch-zoom. +
  • +
  • + Fix Cocoa drawing where style changes were not immediately visible. +
  • +
  • + Fix Cocoa memory leak due to reference cycle. +
  • +
  • + Fix Cocoa bug where notifications were sent after Scintilla was freed. +
  • +
  • + SciTE on OS X user shortcuts treats "Ctrl+D" as equivalent to "Ctrl+d". +
  • +
  • + On Windows, saving SciTE's Lua startup script causes it to run. +
  • +
  • + Limit time allowed to highlight current word in SciTE to 0.25 seconds to remain responsive. +
  • +
  • + Fixed SciTE read-only mode to stick with buffer. +
  • +
  • + For SciTE on Windows, enable Ctrl+Z, Ctrl+X, and Ctrl+C (Undo, Cut, and Copy) in the + editable fields of find and replace strips +
  • +
  • + Remove limit on logical line length in SciTE .properties files. + Bug #3544312. +
  • +
  • + Improve performance of SciTE Save As command. +
  • +
  • + Fix SciTE crash with empty .properties files. Bug #3545938. + Bug #3555308. +
  • +
  • + Fix repeated letter in SciTE calltips. + Bug #3545938. +
  • +
  • + Refine build time checking for Direct2D and DirectWrite. +
  • +
  • + Avoid potential build problems on Windows with MultiMon.h by explicitly checking for multi-monitor APIs. +
  • +
  • + Automatically disable themed drawing in SciTE when building on Windows 2000. + Reenable building for Windows NT 4 on NT 4 . +
  • +
  • + Added ncurses platform definitions. Implementation is maintained separately as + Scinterm. +
  • +
+

+ Release 3.2.1 +

+
    +
  • + Released 14 July 2012. +
  • +
  • + In Scintilla.iface, specify features as properties instead of functions where possible and fix some enumerations. +
  • +
  • + In SciTE Lua scripts, string properties in Scintilla API can be retrieved as well as set using property notation. +
  • +
  • + Added character class APIs: SCI_SETPUNCTUATIONCHARS, SCI_GETWORDCHARS, SCI_GETWHITESPACECHARS, + and SCI_GETPUNCTUATIONCHARS. + Feature #3529805. +
  • +
  • + Less/Hss support added to CSS lexer. + Feature #3532413. +
  • +
  • + C++ lexer style SCE_C_PREPROCESSORCOMMENT added for stream comments in preprocessor. + Bug #3487406. +
  • +
  • + Fix incorrect styling of inactive code in C++ lexer. + Bug #3533036. +
  • +
  • + Fix incorrect styling by C++ lexer after empty lines in preprocessor style. +
  • +
  • + C++ lexer option "lexer.cpp.allow.dollars" fixed so can be turned off after being on. + Bug #3541461. +
  • +
  • + Fortran fixed format lexer fixed to style comments from column 73. + Bug #3540486. +
  • +
  • + Fortran folder folds CRITICAL .. END CRITICAL. + Bug #3540486. +
  • +
  • + Fortran lexer fixes styling after comment line ending with '&'. + Bug #3087226. +
  • +
  • + Fortran lexer styles preprocessor lines so they do not trigger incorrect folding. + Bug #2906275. +
  • +
  • + Fortran folder fixes folding of nested ifs. + Bug #2809176. +
  • +
  • + HTML folder fixes folding of CDATA when fold.html.preprocessor=0. + Bug #3540491. +
  • +
  • + On Cocoa, fix autocompletion font lifetime issue and row height computation. +
  • +
  • + In 'choose single' mode, autocompletion will close an existing list if asked to display a single entry list. +
  • +
  • + Fixed SCI_MARKERDELETE to only delete one marker per call. + Bug #3535806. +
  • +
  • + Properly position caret after undoing coalesced delete operations. + Bug #3523326. +
  • +
  • + Ensure margin is redrawn when SCI_MARGINSETSTYLE called. +
  • +
  • + Fix clicks in first pixel of margins to send SCN_MARGINCLICK. +
  • +
  • + Fix infinite loop when drawing block caret for a zero width space character at document start. +
  • +
  • + Crash fixed for deleting negative range. +
  • +
  • + For characters that overlap the beginning of their space such as italics descenders and bold serifs, allow start + of text to draw 1 pixel into margin. + Bug #699587. + Bug #3537799. +
  • +
  • + Fixed problems compiling Scintilla for Qt with GCC 4.7.1 x64. +
  • +
  • + Fixed problem with determining GTK+ sub-platform caused when adding Qt support in 3.2.0. +
  • +
  • + Fix incorrect measurement of untitled file in SciTE on Linux leading to message "File ...' is 2147483647 bytes long". + Bug #3537764. +
  • +
  • + In SciTE, fix open of selected filename with line number to go to that line. +
  • +
  • + Fix problem with last visible buffer closing in SciTE causing invisible buffers to be active. +
  • +
  • + Avoid blinking of SciTE's current word highlight when output pane changes. +
  • +
  • + SciTE properties files can be longer than 60K. +
  • +
+

+ Release 3.2.0 +

+
    +
  • + Released 1 June 2012. +
  • +
  • + Platform layer added for the Qt open-source cross-platform application and user interface framework + for development in C++ or in Python with the PySide bindings for Qt. +
  • +
  • + Direct access provided to the document bytes for ranges within Scintilla. + This is similar to the existing SCI_GETCHARACTERPOINTER API but allows for better performance. +
  • +
  • + Ctrl+Double Click and Ctrl+Triple Click add the word or line to the set of selections. + Feature #3520037. +
  • +
  • + A SCI_DELETERANGE API was added for deleting a range of text. +
  • +
  • + Line wrap markers may now be drawn in the line number margin. + Feature #3518198. +
  • +
  • + SciTE on OS X adds option to hide hidden files in the open dialog box. +
  • +
  • + Lexer added for OScript language. + Feature #3523197. +
  • +
  • + Lexer added for Visual Prolog language. + Feature #3523018. +
  • +
  • + UTF-8 validity is checked more stringently and consistently. All 66 non-characters are now treated as invalid. +
  • +
  • + HTML lexer bug fixed with inconsistent highlighting for PHP when attribute on separate line from tag. + Bug #3520027. +
  • +
  • + HTML lexer bug fixed for JavaScript block comments. + Bug #3520032. +
  • +
  • + Annotation drawing bug fixed when box displayed with different colours on different lines. + Bug #3519872. +
  • +
  • + On Windows with Direct2D, fix drawing with 125% and 150% DPI system settings. +
  • +
  • + Virtual space selection bug fixed for rectangular selections. + Bug #3519246. +
  • +
  • + Replacing multiple selection with newline changed to only affect main selection. + Bug #3522251. +
  • +
  • + Replacing selection with newline changed to group deletion and insertion as a single undo action. + Bug #3522250. +
  • +
  • + Auto-completion lists on GTK+ 3 set height correctly instead of showing too few lines. +
  • +
  • + Mouse wheel scrolling changed to avoid GTK+ bug in recent distributions. +
  • +
  • + IME bug on Windows fixed for horizontal jump. + Bug #3529728. +
  • +
  • + SciTE case-insensitive autocompletion filters equal identifiers better. + Calltip arrows work with bare word identifiers. + Bug #3517810. +
  • +
  • + SciTE bug fixed where shbang lines not setting file type when switching + to file loaded in background. +
  • +
  • + SciTE on GTK+ shows open and save dialogs with the directory of the current file displayed. +
  • +
+

+ Release 3.1.0 +

+
    +
  • + Released 20 April 2012. +
  • +
  • + Animated find indicator added on Cocoa. +
  • +
  • + Buttons can be made default in SciTE user strips. +
  • +
  • + SciTE allows find and replace histories to be saved in session. +
  • +
  • + Option added to allow case-insensitive selection in auto-completion lists. + Bug #3516538. +
  • +
  • + Replace \0 by complete found text in regular expressions. + Feature #3510979. +
  • +
  • + Fixed single quoted strings in bash lexer. + Bug #3512208. +
  • +
  • + Incorrect highlighting fixed in C++ lexer for continued lines. + Bug #3509317. +
  • +
  • + Hang fixed in diff lexer. + Bug #3508602. +
  • +
  • + Folding improved for SQL CASE/MERGE statement. + Bug #3503277. +
  • +
  • + Fix extra drawing of selection inside word wrap indentation. + Bug #3515555. +
  • +
  • + Fix problem with determining the last line that needs styling when drawing. + Bug #3514882. +
  • +
  • + Fix problems with drawing in margins. + Bug #3514882. +
  • +
  • + Fix printing crash when using Direct2D to display on-screen. + Bug #3513946. +
  • +
  • + Fix SciTE bug where background.*.size disabled restoration of bookmarks and positions from session. + Bug #3514885. +
  • +
  • + Fixed the Move Selected Lines command when last line does not end with a line end character. + Bug #3511023. +
  • +
  • + Fix word wrap indentation printing to use printer settings instead of screen settings. + Bug #3512961. +
  • +
  • + Fix SciTE bug where executing an empty command prevented executing further commands + Bug #3512976. +
  • +
  • + Fix SciTE bugs with focus in user strips and made strips more robust with invalid definitions. +
  • +
  • + Suppress SciTE regular expression option when searching with find next selection. + Bug #3510985. +
  • +
  • + SciTE Find in Files command matches empty pattern to all files. + Feature #3495918. +
  • +
  • + Fix scroll with mouse wheel on GTK+. + Bug #3501321. +
  • +
  • + Fix column finding method so that tab is counted correctly. + Bug #3483713. +
  • +
+

+ Release 3.0.4 +

+
    +
  • + Released 8 March 2012. +
  • +
  • + SciTE scripts can create user interfaces as strips. +
  • +
  • + SciTE can save files automatically in the background. +
  • +
  • + Pinch zoom implemented on Cocoa. +
  • +
  • + ECL lexer added. + Feature #3488209. +
  • +
  • + CPP lexer fixes styling after document comment keywords. + Bug #3495445. +
  • +
  • + Pascal folder improves handling of some constructs. + Feature #3486385. +
  • +
  • + XML lexer avoids entering a bad mode due to complex preprocessor instructions. + Bug #3488060. +
  • +
  • + Duplicate command is always remembered as a distinct command for undo. + Bug #3495836. +
  • +
  • + SciTE xml.auto.close.tags no longer closes with PHP code similar to <a $this-> + Bug #3488067. +
  • +
  • + Fix bug where setting an indicator for the whole document would fail. + Bug #3487440. +
  • +
  • + Crash fixed for SCI_MOVESELECTEDLINESDOWN with empty vertical selection. + Bug #3496403. +
  • +
  • + Differences between buffered and unbuffered mode on Direct2D eliminated. + Bug #3495791. +
  • +
  • + Font leading implemented for Direct2D to improve display of character blobs. + Bug #3494744. +
  • +
  • + Fractional widths used for line numbers, character markers and other situations. + Bug #3494492. +
  • +
  • + Translucent rectangles drawn using Direct2D with sharper corners. + Bug #3494492. +
  • +
  • + RGBA markers drawn sharper when centred using Direct2D. + Bug #3494202. +
  • +
  • + RGBA markers are drawn centred when taller than line. + Bug #3494184. +
  • +
  • + Image marker drawing problem fixed for markers taller than line. + Bug #3493503. +
  • +
  • + Markers are drawn horizontally off-centre based on margin type instead of dimensions. + Bug #3488696. +
  • +
  • + Fold tail markers drawn vertically centred. + Feature #3488289. +
  • +
  • + On Windows, Scintilla is more responsive in wrap mode. + Bug #3487397. +
  • +
  • + Unimportant "Gdk-CRITICAL" messages are no longer displayed. + Bug #3488481. +
  • +
  • + SciTE on Windows Find in Files sets focus to dialog when already created; allows opening dialog when a job is running. + Bug #3480635. + Bug #3486657. +
  • +
  • + Fixed problems with multiple clicks in margin and with mouse actions combined with virtual space. + Bug #3484370. +
  • +
  • + Fixed bug with using page up and down and not returning to original line. + Bug #3485669. +
  • +
  • + Down arrow with wrapped text no longer skips lines. + Bug #1776560. +
  • +
  • + Fix problem with dwell ending immediately due to word wrap. + Bug #3484416. +
  • +
  • + Wrapped lines are rewrapped more consistently while resizing window. + Bug #3484179. +
  • +
  • + Selected line ends are highlighted more consistently. + Bug #3484330. +
  • +
  • + Fix grey background on files that use shbang to choose language. + Bug #3482777. +
  • +
  • + Fix failure messages from empty commands in SciTE. + Bug #3480645. +
  • +
  • + Redrawing reduced for some marker calls. + Feature #3493530. +
  • +
  • + Match brace and select brace commands work in SciTE output pane. + Feature #3486598. +
  • +
  • + Performing SciTE "Show Calltip" command when a calltip is already visible shows the next calltip. + Feature #3487017. +
  • +
  • + SciTE allows saving file even when file unchanged. + Feature #3486654. +
  • +
  • + SciTE allows optional use of character escapes in calltips. + Feature #3495239. +
  • +
  • + SciTE can open file:// URLs with Ctrl+Shift+O. + Feature #3495389. +
  • +
  • + Key modifiers updated for GTK+ on OS X to match upstream changes. +
  • +
  • + SciTE hang when marking all occurrences of regular expressions fixed. +
  • +
+

+ Release 3.0.3 +

+
    +
  • + Released 28 January 2012. +
  • +
  • + Printing works on GTK+ version 2.x as well as 3.x. +
  • +
  • + Lexer added for the AviSynth language. + Feature #3475611. +
  • +
  • + Lexer added for the Take Command / TCC scripting language. + Feature #3462462. +
  • +
  • + CSS lexer gains support for SCSS. + Feature #3268017. +
  • +
  • + CPP lexer fixes problems in the preprocessor structure caused by continuation lines. + Bug #3458508. +
  • +
  • + Errorlist lexer handles column numbers for GCC format diagnostics. + In SciTE, Next Message goes to column where this can be decoded from GCC format diagnostics. + Feature #3453075. +
  • +
  • + HTML folder fixes spurious folds on some tags. + Bug #3459262. +
  • +
  • + Ruby lexer fixes bug where '=' at start of file caused whole file to appear as a comment. + Bug #3452488. +
  • +
  • + SQL folder folds blocks of single line comments. + Feature #3467425. +
  • +
  • + On Windows using Direct2D, defer invalidation of render target until completion of painting to avoid failures. +
  • +
  • + Further support of fractional positioning. Spaces, tabs, and single character tokens can take fractional space + and wrapped lines are positioned taking fractional positions into account. + Bug #3471998. +
  • +
  • + On Windows using Direct2D, fix extra carets appearing. + Bug #3471998. +
  • +
  • + For autocompletion lists Page Up and Down move by the list height instead of by 5 lines. + Bug #3455493. +
  • +
  • + For SCI_LINESCROLLDOWN/UP don't select into virtual space. + Bug #3451681. +
  • +
  • + Fix fold highlight not being fully drawn. + Bug #3469936. +
  • +
  • + Fix selection margin appearing black when starting in wrap mode. +
  • +
  • + Fix crash when changing end of document after adding an annotation. + Bug #3476637. +
  • +
  • + Fix problems with building to make RPMs. + Bug #3476149. +
  • +
  • + Fix problem with building on GTK+ where recent distributions could not find gmodule. + Bug #3469056. +
  • +
  • + Fix problem with installing SciTE on GTK+ due to icon definition in .desktop file including an extension. + Bug #3476117. +
  • +
  • + Fix SciTE bug where new buffers inherited some properties from previously opened file. + Bug #3457060. +
  • +
  • + Fix focus when closing tab in SciTE with middle click. Focus moves to edit pane instead of staying on tab bar. + Bug #3440142. +
  • +
  • + For SciTE on Windows fix bug where Open Selected Filename for URL would append a file extension. + Feature #3459185. +
  • +
  • + For SciTE on Windows fix key handling of control characters in Parameters dialog so normal editing (Ctrl+C, ...) works. + Bug #3459345. +
  • +
  • + Fix SciTE bug where files became read-only after saving. Drop the "*" dirty marker after save completes. + Bug #3467432. +
  • +
  • + For SciTE handling of diffs with "+++" and "---" lines, also handle case where not followed by tab. + Go to correct line for diff "+++" message. + Bug #3467143. + Bug #3467178. +
  • +
  • + SciTE on GTK+ now performs threaded actions even on GTK+ versions before 2.12. +
  • +
+

+ Release 3.0.2 +

+
    +
  • + Released 9 December 2011. +
  • +
  • + SciTE saves files in the background without blocking the user interface. +
  • +
  • + Printing implemented in SciTE on GTK+ 3.x. +
  • +
  • + ILoader interface for background loading finalized and documented. +
  • +
  • + CoffeeScript lexer added. +
  • +
  • + C++ lexer fixes crash with "#if defined( XXX 1". +
  • +
  • + Crash with Direct2D on Windows fixed. +
  • +
  • + Backspace removing protected range fixed. + Bug #3445911. +
  • +
  • + Cursor setting failure on Windows when screen saver on fixed. + Bug #3438780. +
  • +
  • + SciTE on GTK+ hang fixed with -open:file option. + Bug #3441980. +
  • +
  • + Failure to evaluate shbang fixed in SciTE. + Bug #3441801. +
  • +
  • + SciTE failure to treat files starting with "<?xml" as XML fixed. + Bug #3440718. +
  • +
  • + Made untitled tab saveable when created by closing all files. + Bug #3440244. +
  • +
  • + SciTE crash fixed when using Scintillua. +
  • +
  • + SciTE revert command fixed so that undo works on individual actions instead of undoing to revert point. +
  • +
  • + Focus loss in SciTE when opening a recent file fixed. + Bug #3440142. +
  • +
  • + Fixed SciTE SelLength property to measure characters instead of bytes. + Bug #3283519. +
  • +
+

+ Release 3.0.1 +

+
    +
  • + Released 15 November 2011. +
  • +
  • + SciTE on Windows now runs Lua scripts directly on the main thread instead of starting them on a + secondary thread and then moving back to the main thread. +
  • +
  • + Highlight "else" as a keyword for TCL in the same way as other languages. + Bug #1836954. +
  • +
  • + Fix problems with setting fonts for autocompletion lists on Windows where + font handles were copied and later deleted causing a system default font to be used. +
  • +
  • + Fix font size used on Windows for Asian language input methods which sometimes led to IME not being visible. + Bug #3436753. +
  • +
  • + Fixed polygon drawing on Windows so fold symbols are visible again. + Bug #3433558. +
  • +
  • + Changed background drawing on GTK+ to allow for fractional character positioning as occurs on OS X + as this avoids faint lines at lexeme boundaries. +
  • +
  • + Ensure pixmaps allocated before painting as there was a crash when Scintilla drew without common initialization calls. + Bug #3432354. +
  • +
  • + Fixed SciTE on Windows bug causing wrong caret position after indenting a selection. + Bug #3433433. +
  • +
  • + Fixed SciTE session saving to store buffer position matching buffer. + Bug #3434372. +
  • +
  • + Fixed leak of document objects in SciTE. +
  • +
  • + Recognize URL characters '?' and '%' for Open Selected command in SciTE. + Bug #3429409. +
  • +
+

+ Release 3.0.0 +

+
    +
  • + Released 1 November 2011. +
  • +
  • + Carbon platform support removed. OS X applications should switch to Cocoa. +
  • +
  • + On Windows Vista or newer, drawing may be performed with Direct2D and DirectWrite instead of GDI. +
  • +
  • + Cairo is now used for all drawing on GTK+. GDK drawing was removed. +
  • +
  • + Paletted display support removed. +
  • +
  • + Fractional font sizes can be specified. +
  • +
  • + Different weights of text supported on some platforms instead of just normal and bold. +
  • +
  • + Sub-pixel character positioning supported. +
  • +
  • + SciTE loads files in the background without blocking the user interface. +
  • +
  • + SciTE can display diagnostic messages interleaved with the text of files immediately after the + line referred to by the diagnostic. +
  • +
  • + New API to see if all lines are visible which can be used to optimize processing fold structure notifications. +
  • +
  • + Scrolling optimized by avoiding invalidation of fold margin when redrawing whole window. +
  • +
  • + Optimized SCI_MARKERNEXT. +
  • +
  • + C++ lexer supports Pike hash quoted strings when turned on with lexer.cpp.hashquoted.strings. +
  • +
  • + Fixed incorrect line height with annotations in wrapped mode when there are multiple views. + Bug #3388159. +
  • +
  • + Calltips may be displayed above the text as well as below. + Bug #3410830. +
  • +
  • + For huge files SciTE only examines the first megabyte for newline discovery. +
  • +
  • + SciTE on GTK+ removes the fileselector.show.hidden property and check box as this was buggy and GTK+ now + supports an equivalent feature. + Bug #3413630. +
  • +
  • + SciTE on GTK+ supports mnemonics in dynamic menus. +
  • +
  • + SciTE on GTK+ displays the user's home directory as '~' in menus to make them shorter. +
  • +
+

+ Release 2.29 +

+
    +
  • + Released 16 September 2011. +
  • +
  • + To automatically discover the encoding of a file when opening it, SciTE can run a program set with command.discover.properties. + Feature #3324341. +
  • +
  • + Cairo always used for drawing on GTK+. +
  • +
  • + The set of properties files imported by SciTE can be controlled with the properties imports.include and imports.exclude. + The import statement has been extended to allow "import *". + The properties files for some languages are no longer automatically loaded by default. The properties files affected are + avenue, baan, escript, lot, metapost, and mmixal. +
  • +
  • + C++ lexer fixed a bug with raw strings being recognized too easily. + Bug #3388122. +
  • +
  • + LaTeX lexer improved with more states and fixes to most outstanding bugs. + Bug #1493111. + Bug #1856356. + Bug #3081692. +
  • +
  • + Lua lexer updates for Lua 5.2 beta with goto labels and "\z" string escape. + Feature #3386330. +
  • +
  • + Perl string styling highlights interpolated variables. + Feature #3394258. + Bug #3076629. +
  • +
  • + Perl lexer updated for Perl 5.14.0 with 0X and 0B numeric literal prefixes, break keyword and "+" supported in subroutine prototypes. + Feature #3388802. +
  • +
  • + Perl bug fixed with CRLF line endings. +
  • +
  • + Markdown lexer fixed to not change state with "_" in middle of word. + Bug #3398184. +
  • +
  • + Cocoa restores compatibility with OS X 10.5. +
  • +
  • + Mouse pointer changes over selection to an arrow near start when scrolled horizontally. + Bug #3389055. +
  • +
  • + Indicators that finish at the end of the document no longer expand when text is appended. + Bug #3378718. +
  • +
  • + SparseState merge fixed to check if other range is empty. + Bug #3387053. +
  • +
  • + On Windows, autocompletion lists will scroll instead of document when mouse wheel spun. + Feature #3403600. +
  • +
  • + SciTE performs more rapid polling for command completion so will return faster and report more accurate times. +
  • +
  • + SciTE resizes panes proportionally when switched between horizontal and vertical layout. + Feature #3376784. +
  • +
  • + SciTE on GTK+ opens multiple files into a single instance more reliably. + Bug #3363754. +
  • +
+

+ Release 2.28 +

+
    +
  • + Released 1 August 2011. +
  • +
  • + GTK+ Cairo support works back to GTK+ version 2.8. Requires changing Scintilla source code to enable before GTK+ 2.22. + Bug #3322351. +
  • +
  • + Translucent images in RGBA format can be used for margin markers and in autocompletion lists. +
  • +
  • + INDIC_DOTBOX added as a translucent dotted rectangular indicator. +
  • +
  • + Asian text input using IME works for GTK+ 3.x and GTK+ 2.x with Cairo. +
  • +
  • + On GTK+, IME works for Ctrl+Shift+U Unicode input in Scintilla. For SciTE, Ctrl+Shift+U is still Make Selection Uppercase. +
  • +
  • + Key bindings for GTK+ on OS X made compatible with Cocoa port and platform conventions. +
  • +
  • + Cocoa port supports different character encodings, improves scrolling performance and drag image appearance. + The control ID is included in WM_COMMAND notifications. Text may be deleted by dragging to the trash. + ScrollToStart and ScrollToEnd key commands added to simplify implementation of standard OS X Home and End + behaviour. +
  • +
  • + SciTE on GTK+ uses a paned widget to contain the edit and output panes instead of custom code. + This allows the divider to be moved easily on GTK+ 3 and its appearance follows GTK+ conventions more closely. +
  • +
  • + SciTE builds and installs on BSD. + Bug #3324644. +
  • +
  • + Cobol supports fixed format comments. + Bug #3014850. +
  • +
  • + Mako template language block syntax extended and ## comments recognized. + Feature #3325178. + Bug #3318818. +
  • +
  • + Folding of Mako template language within HTML fixed. + Bug #3324563. +
  • +
  • + Python lexer has lexer.python.keywords2.no.sub.identifiers option to avoid highlighting second set of + keywords following '.'. + Bug #3325333. +
  • +
  • + Python folder fixes bug where fold would not extend to final line. + Bug #3349157. +
  • +
  • + SciTE treats LPEG lexers the same as script lexers by setting all 8 style bits. +
  • +
  • + For Cocoa, crashes with unsupported font variants and memory leaks for colour objects fixed. +
  • +
  • + Shift-JIS lead byte ranges modified to match Windows. +
  • +
  • + Mouse pointer changes over selection to an arrow more consistently. + Bug #3315756. +
  • +
  • + Bug fixed with annotations beyond end of document. + Bug #3347268. +
  • +
  • + Incorrect drawing fixed for combination of background colour change and translucent selection. + Bug #3377116. +
  • +
  • + Lexers initialized correctly when started at position other than start of line. + Bug #3377148. +
  • +
  • + Fold highlight drawing fixed for some situations. + Bug #3323015. + Bug #3323805. +
  • +
  • + Case insensitive search fixed for cases where folded character uses fewer bytes than base character. + Bug #3362038. +
  • +
  • + SciTE bookmark.alpha setting fixed. + Bug #3373907. +
  • +
+

+ Release 2.27 +

+
    +
  • + Released 20 June 2011. +
  • +
  • + On recent GTK+ 2.x versions when using Cairo, bug fixed where wrong colours were drawn. +
  • +
  • + SciTE on GTK+ slow performance in menu maintenance fixed. + Bug #3315233. +
  • +
  • + Cocoa platform supports 64-bit builds and uses only non-deprecated APIs. + Asian Input Method Editors are supported. + Autocompletion lists and calltips implemented. + Control identifier used in notifications. +
  • +
  • + On Cocoa, rectangular selection now uses Option/Alt key to be compatible with Apple Human + Interface Guidelines and other applications. + The Control key is reported with an SCMOD_META modifier bit. +
  • +
  • + API added for setting and retrieving the identifier number used in notifications. +
  • +
  • + SCI_SETEMPTYSELECTION added to set selection without scrolling or redrawing more than needed. + Feature #3314877. +
  • +
  • + Added new indicators. INDIC_DASH and INDIC_DOTS are variants of underlines. + INDIC_SQUIGGLELOW indicator added as shorter alternative to INDIC_SQUIGGLE for small fonts. + Bug #3314591 +
  • +
  • + Margin line selection can be changed to select display lines instead of document lines. + Bug #3312763. +
  • +
  • + On Windows, SciTE can perform reverse searches by pressing Shift+Enter + in the Find or Replace strips or dialogs. +
  • +
  • + Matlab lexer does not special case '\' in single quoted strings. + Bug #948757 + Bug #1755950 + Bug #1888738 + Bug #3316852. +
  • +
  • + Verilog lexer supports SystemVerilog folding and keywords. +
  • +
  • + Font leak fixed. + Bug #3306156. +
  • +
  • + Automatic scrolling works for long wrapped lines. + Bug #3312763. +
  • +
  • + Multiple typing works for cases where selections collapse together. + Bug #3309906. +
  • +
  • + Fold expanded when needed in word wrap mode. + Bug #3291579. +
  • +
  • + Bug fixed with edge drawn in wrong place on wrapped lines. + Bug #3314807. +
  • +
  • + Bug fixed with unnecessary scrolling for SCI_GOTOLINE. + Bug #3303406. +
  • +
  • + Bug fixed where extra step needed to undo SCI_CLEAR in virtual space. + Bug #3159691. +
  • +
  • + Regular expression search fixed for \$ on last line of search range. + Bug #3313746. +
  • +
  • + SciTE performance improved when switching to a tab with a very large file. + Bug #3311421. +
  • +
  • + On Windows, SciTE advanced search remembers the "Search only in this style" setting. + Bug #3313344. +
  • +
  • + On GTK+, SciTE opens help using "xdg-open" instead of "netscape" as "netscape" no longer commonly installed. + Bug #3314377. +
  • +
  • + SciTE script lexers can use 256 styles. +
  • +
  • + SciTE word highlight works for words containing DBCS characters. + Bug #3315173. +
  • +
  • + Compilation fixed for wxWidgets. + Bug #3306156. +
  • +
+

+ Release 2.26 +

+
    +
  • + Released 25 May 2011. +
  • +
  • + Folding margin symbols can be highlighted for the current folding block. + Feature #3147069. +
  • +
  • + Selected lines can be moved up or down together. + Feature #3304850. +
  • +
  • + SciTE can highlight all occurrences of the current word or selected text. + Feature #3291636. +
  • +
  • + Experimental GTK+ 3.0 support: build with "make GTK3=1". +
  • +
  • + INDIC_STRAIGHTBOX added. Is similar to INDIC_ROUNDBOX but without rounded corners. + Bug #3290435. +
  • +
  • + Can show brace matching and mismatching with indicators instead of text style. + Translucency of outline can be altered for INDIC_ROUNDBOX and INDIC_STRAIGHTBOX. + Feature #3290434. +
  • +
  • + SciTE can automatically indent python by examining previous line for scope-starting ':' with indent.python.colon. +
  • +
  • + Batch file lexer allows braces '(' or ')' inside variable names. +
  • +
  • + The cpp lexer only recognizes Vala triple quoted strings when lexer.cpp.triplequoted.strings property is set. + Bug #3239234. +
  • +
  • + Make file lexer treats a variable with a nested variable like $(f$(qx)b) as one variable. + Bug #3298223. +
  • +
  • + Folding bug fixed for JavaScript with nested PHP. + Bug #3193530. +
  • +
  • + HTML lexer styles Django's {# #} comments. + Bug #3013798. +
  • +
  • + HTML lexer styles JavaScript regular expression correctly for /abc/i.test('abc');. + Bug #3209108. +
  • +
  • + Inno Setup Script lexer now works properly when it restarts from middle of [CODE] section. + Bug #3283880. + Bug #3129044. +
  • +
  • + Lua lexer updated for Lua 5.2 with hexadecimal floating-point numbers and '\*' whitespace escaping in strings. + Feature #3243811. +
  • +
  • + Perl folding folds "here doc"s and adds options fold.perl.at.else and fold.perl.comment.explicit. Fold structure for Perl fixed. + Feature #3112671. + Bug #3265401. +
  • +
  • + Python lexer supports cpdef keyword for Cython. + Bug #3279728. +
  • +
  • + SQL folding option lexer.sql.fold.at.else renamed to fold.sql.at.else. + Bug #3271474. +
  • +
  • + SQL lexer no longer treats ';' as terminating a comment. + Bug #3196071. +
  • +
  • + Text drawing and measurement segmented into smaller runs to avoid platform bugs. + Bug #3277449. + Bug #3165743. +
  • +
  • + SciTE on Windows adds temp.files.sync.load property to open dropped temporary files synchronously as they may + be removed before they can be opened asynchronously. + Bug #3072009. +
  • +
  • + Bug fixed with indentation guides ignoring first line in SC_IV_LOOKBOTH mode. + Bug #3291317. +
  • +
  • + Bugs fixed in backward regex search. + Bug #3292659. +
  • +
  • + Bugs with display of folding structure fixed for wrapped lines and where there is a fold header but no body. + Bug #3291579. + Bug #3265401. +
  • +
  • + SciTE on Windows cursor changes to an arrow now when over horizontal splitter near top of window. + Bug #3286620. +
  • +
  • + Fixed default widget size problem on GTK+. + Bug #3267892. +
  • +
  • + Fixed font size when using Cairo on GTK+. + Bug #3272662. +
  • +
  • + Fixed primary selection and cursor issues on GTK+ when unrealized then realized. + Bug #3256153. +
  • +
  • + Right click now cancels selection on GTK+ like on Windows. + Bug #3235190. +
  • +
  • + SciTE on GTK+ implements z-order buffer switching like on Windows. + Bug #3228384. +
  • +
  • + Improve selection position after SciTE Insert Abbreviation command when abbreviation expansion includes '|'. +
  • +
+

+ Release 2.25 +

+
    +
  • + Released 21 March 2011. +
  • +
  • + SparseState class makes it easier to write lexers which have to remember complex state between lines. +
  • +
  • + Visual Studio project (.dsp) files removed. The make files should be used instead as described in the README. +
  • +
  • + Modula 3 lexer added along with SciTE support. + Feature #3173374. +
  • +
  • + Asm, Basic, and D lexers add extra folding properties. +
  • +
  • + Raw string literals for C++0x supported in C++ lexer. +
  • +
  • + Triple-quoted strings used in Vala language supported in C++ lexer. + Feature #3177601. +
  • +
  • + The errorlist lexer used in SciTE's output pane colours lines that start with '<' as diff deletions. + Feature #3172878. +
  • +
  • + The Fortran lexer correctly folds type-bound procedures from Fortran 2003. +
  • +
  • + LPeg lexer support‎ improved in SciTE. +
  • +
  • + SciTE on Windows-64 fixes for menu localization and Lua scripts. + Bug #3204502. +
  • +
  • + SciTE on Windows avoids locking folders when using the open or save dialogs. + Bug #1795484. +
  • +
  • + Diff lexer fixes problem where diffs of diffs producing lines that start with "----". + Bug #3197952. +
  • +
  • + Bug fixed when searching upwards in Chinese code page 936. + Bug #3176271. +
  • +
  • + On Cocoa, translucent drawing performed as on other platforms instead of 2.5 times less translucent. +
  • +
  • + Performance issue and potential bug fixed on GTK+ with caret line for long lines. +
  • +
+

+ Release 2.24 +

+
    +
  • + Released 3 February 2011. +
  • +
  • + Fixed memory leak in GTK+ Cairo code. + Feature #3157655. +
  • +
  • + Insert Abbreviation dialog added to SciTE on GTK+. +
  • +
  • + SCN_UPDATEUI notifications received when window scrolled. An 'updated' bit mask indicates which + types of update have occurred from SC_UPDATE_SELECTION, SC_UPDATE_CONTENT, SC_UPDATE_H_SCROLL + or SC_UPDATE_V_SCROLL. + Feature #3125977. +
  • +
  • + On Windows, to ensure reverse arrow cursor matches platform default, it is now generated by + reflecting the platform arrow cursor. + Feature #3143968. +
  • +
  • + Can choose mouse cursor used in margins. + Feature #3161326. +
  • +
  • + On GTK+, SciTE sets a mime type of text/plain in its .desktop file so that it will appear in the shell context menu. + Feature #3137126. +
  • +
  • + Bash folder handles here docs. + Feature #3118223. +
  • +
  • + C++ folder adds fold.cpp.syntax.based, fold.cpp.comment.multiline, fold.cpp.explicit.start, fold.cpp.explicit.end, + and fold.cpp.explicit.anywhere properties to allow more control over folding and choice of explicit fold markers. +
  • +
  • + C++ lexer fixed to always handle single quote strings continued past a line end. + Bug #3150522. +
  • +
  • + Ruby folder handles here docs. + Feature #3118224. +
  • +
  • + SQL lexer allows '.' to be part of words. + Feature #3103129. +
  • +
  • + SQL folder handles case statements in more situations. + Feature #3135027. +
  • +
  • + SQL folder adds fold points inside expressions based on bracket structure. + Feature #3165488. +
  • +
  • + SQL folder drops fold.sql.exists property as 'exists' is handled automatically. + Bug #3164194. +
  • +
  • + SciTE only forwards properties to lexers when they have been explicitly set so the defaults set by lexers are used + rather than 0. +
  • +
  • + Mouse double click word selection chooses the word around the character under the mouse rather than + the inter-character position under the mouse. This makes double clicking select what the user is pointing + at and avoids selecting adjacent non-word characters. + Bug #3111174. +
  • +
  • + Fixed mouse double click to always perform word select, not line select. + Bug #3143635. +
  • +
  • + Right click cancels autocompletion. + Bug #3144531. +
  • +
  • + Fixed multiPaste to work when additionalSelectionTyping off. + Bug #3126221. +
  • +
  • + Fixed virtual space problems when text modified at caret. + Bug #3154986. +
  • +
  • + Fixed memory leak in lexer object code. + Bug #3133672. +
  • +
  • + Fixed SciTE on GTK+ search failure when using regular expression. + Bug #3156217. +
  • +
  • + Avoid unnecessary full window redraw for SCI_GOTOPOS. + Feature #3146650. +
  • +
  • + Avoid unnecessary redraw when indicator fill range makes no real change. +
  • +
+

+ Release 2.23 +

+
    +
  • + Released 7 December 2010. +
  • +
  • + On GTK+ version 2.22 and later, drawing is performed with Cairo rather than GDK. + This is in preparation for GTK+ 3.0 which will no longer support GDK drawing. + The appearance of some elements will be different with Cairo as it is anti-aliased and uses sub-pixel positioning. + Cairo may be turned on for GTK+ versions before 2.22 by defining USE_CAIRO although this has not + been extensively tested. +
  • +
  • + New lexer a68k for Motorola 68000 assembler. + Feature #3101598. +
  • +
  • + Borland C++ is no longer supported for building Scintilla or SciTE on Windows. +
  • +
  • + Performance improved when creating large rectangular selections. +
  • +
  • + PHP folder recognizes #region and #endregion comments. + Feature #3101624. +
  • +
  • + SQL lexer has a lexer.sql.numbersign.comment option to turn off use of '#' comments + as these are a non-standard feature only available in some implementations. + Feature #3098071. +
  • +
  • + SQL folder recognizes case statements and understands the fold.at.else property. + Bug #3104091. + Bug #3107362. +
  • +
  • + SQL folder fixes bugs with end statements when fold.sql.only.begin=1. + Bug #3104091. +
  • +
  • + SciTE on Windows bug fixed with multi-line tab bar not adjusting correctly when maximizing and demaximizing. + Bug #3097517. +
  • +
  • + Crash fixed on GTK+ when Scintilla widget destroyed while it still has an outstanding style idle pending. +
  • +
  • + Bug fixed where searching backwards in DBCS text (code page 936 or similar) failed to find occurrences at the start of the line. + Bug #3103936. +
  • +
  • + SciTE on Windows supports Unicode file names when executing help applications with winhelp and htmlhelp subsystems. +
  • +
+

+ Release 2.22 +

+
    +
  • + Released 27 October 2010. +
  • +
  • + SciTE includes support for integrating with Scintillua which allows lexers to be implemented in Lua as a + Parsing Expression Grammar (PEG). +
  • +
  • + Regular expressions allow use of '?' for non-greedy matches or to match 0 or 1 instances of an item. +
  • +
  • + SCI_CONTRACTEDFOLDNEXT added to allow rapid retrieval of folding state. +
  • +
  • + SCN_HOTSPOTRELEASECLICK notification added which is similar to SCN_HOTSPOTCLICK but occurs + when the mouse is released. + Feature #3082409. +
  • +
  • + Command added for centring current line in window. + Feature #3064696. +
  • +
  • + SciTE performance improved by not examining document for line ends when switching buffers and not + storing folds when folding turned off. +
  • +
  • + Bug fixed where scrolling to ensure the caret is visible did not take into account all pixels of the line. + Bug #3081721. +
  • +
  • + Bug fixed for autocompletion list overlapping text when WS_EX_CLIENTEDGE used. + Bug #3079778. +
  • +
  • + After autocompletion, the caret's X is updated. + Bug #3079114. +
  • +
  • + On Windows, default to the system caret blink time. + Feature #3079784. +
  • +
  • + PgUp/PgDn fixed to allow virtual space. + Bug #3077452. +
  • +
  • + Crash fixed when AddMark and AddMarkSet called with negative argument. + Bug #3075074. +
  • +
  • + Dwell notifications fixed so that they do not occur when the mouse is outside Scintilla. + Bug #3073481. +
  • +
  • + Bash lexer bug fixed for here docs starting with <<-. + Bug #3063822. +
  • +
  • + C++ lexer bug fixed for // comments that are continued onto a second line by a \. + Bug #3066031. +
  • +
  • + C++ lexer fixes wrong highlighting for float literals containing +/-. + Bug #3058924. +
  • +
  • + JavaScript lexer recognize regexes following return keyword.‎ + Bug #3062287. +
  • +
  • + Ruby lexer handles % quoting better and treats range dots as operators in 1..2 and 1...2. + Ruby folder handles "if" keyword used as a modifier even when it is separated from the modified statement by an escaped new line. + Bug #2093767. + Bug #3058496. +
  • +
  • + Bug fixed where upwards search failed with DBCS code pages. + Bug #3065912. +
  • +
  • + SciTE has a default Lua startup script name distributed in SciTEGlobal.properties. + No error message is displayed if this file does not exist. +
  • +
  • + SciTE on Windows tab control height is calculated better. + Bug #2635702. +
  • +
  • + SciTE on Windows uses better themed check buttons in find and replace strips. +
  • +
  • + SciTE on Windows fixes bug with Find strip appearing along with Incremental Find strip. +
  • +
  • + SciTE setting find.close.on.find added to allow preventing the Find dialog from closing. +
  • +
  • + SciTE on Windows attempts to rerun commands that fail by prepending them with "cmd.exe /c". + This allows commands built in to the command processor like "dir" to run. +
  • +
+

+ Release 2.21 +

+
    +
  • + Released 1 September 2010. +
  • +
  • + Asian Double Byte Character Set (DBCS) support improved. + Case insensitive search works and other operations are much faster. + Bug #2999125, + Bug #2774616, + Bug #2991942, + Bug #3005688. +
  • +
  • + Scintilla on GTK+ uses only non-deprecated APIs (for GTK+ 2.20) except for GdkFont and GdkFont use can be disabled + with the preprocessor symbol DISABLE_GDK_FONT. +
  • +
  • + IDocument interface used by lexers adds BufferPointer and GetLineIndentation methods. +
  • +
  • + On Windows, clicking sets focus before processing the click or sending notifications. +
  • +
  • + Bug on OS X (macosx platform) fixed where drag/drop overwrote clipboard. + Bug #3039732. +
  • +
  • + GTK+ drawing bug when the view was horizontally scrolled more than 32000 pixels fixed. +
  • +
  • + SciTE bug fixed with invoking Complete Symbol from output pane. + Bug #3050957. +
  • +
  • + Bug fixed where it was not possible to disable folding. + Bug #3040649. +
  • +
  • + Bug fixed with pressing Enter on a folded fold header line not opening the fold. + Bug #3043419. +
  • +
  • + SciTE 'Match case' option in find and replace user interfaces changed to 'Case sensitive' to allow use of 'v' + rather than 'c' as the mnemonic. +
  • +
  • + SciTE displays stack trace for Lua when error occurs.. + Bug #3051397. +
  • +
  • + SciTE on Windows fixes bug where double clicking on error message left focus in output pane. + Bug #1264835. +
  • +
  • + SciTE on Windows uses SetDllDirectory to avoid a security problem. +
  • +
  • + C++ lexer crash fixed with preprocessor expression that looked like division by 0. + Bug #3056825. +
  • +
  • + Haskell lexer improved. + Feature #3039490. +
  • +
  • + HTML lexing fixed around Django {% %} tags. + Bug #3034853. +
  • +
  • + HTML JavaScript lexing fixed when line end escaped. + Bug #3038381. +
  • +
  • + HTML lexer stores line state produced by a line on that line rather than on the next line. +
  • +
  • + Markdown lexer fixes infinite loop. + Bug #3045386. +
  • +
  • + MySQL folding bugs with END statements fixed. + Bug #3031742. +
  • +
  • + PowerShell lexer allows '_' as a word character. + Feature #3042228. +
  • +
  • + SciTE on GTK+ abandons processing of subsequent commands if a command.go.needs command fails. +
  • +
  • + When SciTE is closed, all buffers now receive an OnClose call. + Bug #3033857. +
  • +
+

+ Release 2.20 +

+
    +
  • + Released 30 July 2010. +
  • +
  • + Lexers are implemented as objects so that they may retain extra state. + The interfaces defined for this are tentative and may change before the next release. + Compatibility classes allow current lexers compiled into Scintilla to run with few changes. + The interface to external lexers has changed and existing external lexers will need to have changes + made and be recompiled. + A single lexer object is attached to a document whereas previously lexers were attached to views + which could lead to different lexers being used for split views with confusing results. +
  • +
  • + C++ lexer understands the preprocessor enough to grey-out inactive code due to conditional compilation. +
  • +
  • + SciTE can use strips within the main window for find and replace rather than dialogs. + On Windows SciTE always uses a strip for incremental search. +
  • +
  • + Lexer added for Txt2Tags language. + Feature #3018736. +
  • +
  • + Sticky caret feature enhanced with additional SC_CARETSTICKY_WHITESPACE mode . + Feature #3027559. +
  • +
  • + Bash lexer implements basic parsing of compound commands and constructs. + Feature #3033135. +
  • +
  • + C++ folder allows disabling explicit fold comments. +
  • +
  • + Perl folder works for array blocks, adjacent package statements, nested PODs, and terminates package folding at __DATA__, ^D and ^Z. + Feature #3030887. +
  • +
  • + PowerShell lexer supports multiline <# .. #> comments and adds 2 keyword classes. + Feature #3015176. +
  • +
  • + Lexing performed incrementally when needed by wrapping to make user interface more responsive. +
  • +
  • + SciTE setting replaceselection:yes works on GTK+. +
  • +
  • + SciTE Lua scripts calling io.open or io.popen on Windows have arguments treated as UTF-8 and converted to Unicode + so that non-ASCII file paths will work. Lua files with non-ASCII paths run. + Bug #3016951. +
  • +
  • + Crash fixed when searching for empty string. + Bug #3017572. +
  • +
  • + Bugs fixed with folding and lexing when Enter pressed at start of line. + Bug #3032652. +
  • +
  • + Bug fixed with line selection mode not affecting selection range. + Bug #3021480. +
  • +
  • + Bug fixed where indicator alpha was limited to 100 rather than 255. + Bug #3021473. +
  • +
  • + Bug fixed where changing annotation did not cause automatic redraw. +
  • +
  • + Regular expression bug fixed when a character range included non-ASCII characters. +
  • +
  • + Compilation failure with recent compilers fixed on GTK+. + Bug #3022027. +
  • +
  • + Bug fixed on Windows with multiple monitors where autocomplete pop up would appear off-screen + or straddling monitors. + Bug #3017512. +
  • +
  • + SciTE on Windows bug fixed where changing directory to a Unicode path failed. + Bug #3011987. +
  • +
  • + SciTE on Windows bug fixed where combo boxes were not allowing Unicode characters. + Bug #3012986. +
  • +
  • + SciTE on GTK+ bug fixed when dragging files into SciTE on KDE. + Bug #3026555. +
  • +
  • + SciTE bug fixed where closing untitled file could lose data if attempt to name file same as another buffer. + Bug #3011680. +
  • +
  • + COBOL number masks now correctly highlighted. + Bug #3012164. +
  • +
  • + PHP comments can include <?PHP without triggering state change. + Bug #2854183. +
  • +
  • + VHDL lexer styles unclosed string correctly. + Bug #3029627. +
  • +
  • + Memory leak fixed in list boxes on GTK+. + Bug #3007669. +
  • +
+

+ Release 2.12 +

+
    +
  • + Released 1 June 2010. +
  • +
  • + Drawing optimizations improve speed and fix some visible flashing when scrolling. +
  • +
  • + Copy Path command added to File menu in SciTE. + Feature #2986745. +
  • +
  • + Optional warning displayed by SciTE when saving a file which has been modified by another process. + Feature #2975041. +
  • +
  • + Flagship lexer for xBase languages updated to follow the language much more closely. + Feature #2992689. +
  • +
  • + HTML lexer highlights Django templates in more regions. + Feature #3002874. +
  • +
  • + Dropping files on SciTE on Windows, releases the drag object earlier and opens the files asynchronously, + leading to smoother user experience. + Feature #2986724. +
  • +
  • + SciTE HTML exports take the Use Monospaced Font setting into account. +
  • +
  • + SciTE window title "[n of m]" localized. +
  • +
  • + When new line inserted at start of line, markers are moved down. + Bug #2986727. +
  • +
  • + On Windows, dropped text has its line ends converted, similar to pasting. + Bug #3005328. +
  • +
  • + Fixed bug with middle-click paste in block select mode where text was pasted next to selection rather than at cursor. + Bug #2984460. +
  • +
  • + Fixed SciTE crash where a style had a size parameter without a value. + Bug #3003834. +
  • +
  • + Debug assertions in multiple lexers fixed. + Bug #3000566. +
  • +
  • + CSS lexer fixed bug where @font-face displayed incorrectly + Bug #2994224. +
  • +
  • + CSS lexer fixed bug where open comment caused highlighting error. + Bug #1683672. +
  • +
  • + Shell file lexer fixed highlight glitch with here docs where the first line is a comment. + Bug #2830239. +
  • +
  • + Bug fixed in SciTE openpath property that caused Open Selected File to fail to open the selected file. +
  • +
  • + Bug fixed in SciTE FileExt property when file name with no extension evaluated to whole path. +
  • +
  • + Fixed SciTE on Windows printing bug where the $(CurrentTime), $(CurrentPage) variables were not expanded. + Bug #2994612. +
  • +
  • + SciTE compiles for 64-bit Windows and runs without crashing. + Bug #2986312. +
  • +
  • + Full Screen mode in Windows Vista/7 improved to hide Start button and size borders a little better. + Bug #3002813. +
  • +
+

+ Release 2.11 +

+
    +
  • + Released 9 April 2010. +
  • +
  • + Fixes compatibility of Scintilla.h with the C language. +
  • +
  • + With a rectangular selection SCI_GETSELECTIONSTART and SCI_GETSELECTIONEND return limits of the + rectangular selection rather than the limits of the main selection. +
  • +
  • + When SciTE on Windows is minimized to tray, only takes a single click to restore rather than a double click. + Feature #981917. +
  • +
+

+ Release 2.10 +

+
    +
  • + Released 4 April 2010. +
  • +
  • + Version 1.x of GTK+ is no longer supported. +
  • +
  • + SciTE is no longer supported on Windows 95, 98 or ME. +
  • +
  • + Case-insensitive search works for non-ASCII characters in UTF-8 and 8-bit encodings. + Non-regex search in DBCS encodings is always case-sensitive. +
  • +
  • + Non-ASCII characters may be changed to upper and lower case. +
  • +
  • + SciTE on Windows can access all files including those with names outside the user's preferred character encoding. +
  • +
  • + SciTE may be extended with lexers written in Lua. +
  • +
  • + When there are multiple selections, the paste command can go either to the main selection or to each + selection. This is controlled with SCI_SETMULTIPASTE. +
  • +
  • + More forms of bad UTF-8 are detected including overlong sequences, surrogates, and characters outside + the valid range. Bad UTF-8 bytes are now displayed as 2 hex digits preceded by 'x'. +
  • +
  • + SCI_GETTAG retrieves the value of captured expressions within regular expression searches. +
  • +
  • + Django template highlighting added to the HTML lexer. + Feature #2974889. +
  • +
  • + Verilog line comments can be folded. +
  • +
  • + SciTE on Windows allows specifying a filter for the Save As dialog. + Feature #2943445. +
  • +
  • + Bug fixed when multiple selection disabled where rectangular selections could be expanded into multiple selections. + Bug #2948260. +
  • +
  • + Bug fixed when document horizontally scrolled and up/down-arrow did not return to the same + column after horizontal scroll occurred. + Bug #2950799. +
  • +
  • + Bug fixed to remove hotspot highlight when mouse is moved out of the document. Windows only fix. + Bug #2951353. +
  • +
  • + R lexer now performs case-sensitive check for keywords. + Bug #2956543. +
  • +
  • + Bug fixed on GTK+ where text disappeared when a wrap occurred. + Bug #2958043. +
  • +
  • + Bug fixed where regular expression replace cannot escape the '\' character by using '\\'. + Bug #2959876. +
  • +
  • + Bug fixed on GTK+ when virtual space disabled, middle-click could still paste text beyond end of line. + Bug #2971618. +
  • +
  • + SciTE crash fixed when double clicking on a malformed error message in the output pane. + Bug #2976551. +
  • +
  • + Improved performance on GTK+ when changing parameters associated with scroll bars to the same value. + Bug #2964357. +
  • +
  • + Fixed bug with pressing Shift+Tab with a rectangular selection so that it performs an un-indent + similar to how Tab performs an indent. +
  • +
+

+ Release 2.03 +

+
    +
  • + Released 14 February 2010. +
  • +
  • + Added SCI_SETFIRSTVISIBLELINE to match SCI_GETFIRSTVISIBLELINE. +
  • +
  • + Erlang lexer extended set of numeric bases recognized; separate style for module:function_name; detects + built-in functions, known module attributes, and known preprocessor instructions; recognizes EDoc and EDoc macros; + separates types of comments. + Bug #2942448. +
  • +
  • + Python lexer extended with lexer.python.strings.over.newline option that allows non-triple-quoted strings to extend + past line ends. This allows use of the Ren'Py language. + Feature #2945550. +
  • +
  • + Fixed bugs with cursor movement after deleting a rectangular selection. + Bug #2942131. +
  • +
  • + Fixed bug where calling SCI_SETSEL when there is a rectangular selection left + the additional selections selected. + Bug #2947064. +
  • +
  • + Fixed macro recording bug where not all bytes in multi-byte character insertions were reported through + SCI_REPLACESEL. +
  • +
  • + Fixed SciTE bug where using Ctrl+Enter followed by Ctrl+Space produced an autocompletion list + with only a single line containing all the identifiers. +
  • +
  • + Fixed SciTE on GTK+ bug where running a tool made the user interface completely unresponsive. +
  • +
  • + Fixed SciTE on Windows Copy to RTF bug. + Bug #2108574. +
  • +
+

+ Release 2.02 +

+
    +
  • + Released on 25 January 2010. +
  • +
  • + Markdown lexer added. + Feature #2844081. +
  • +
  • + On GTK+, include code that understands the ranges of lead bytes for code pages 932, 936, and 950 + so that most Chinese and Japanese text can be used on systems that are not set to the corresponding locale. +
  • +
  • + Allow changing the size of dots in visible whitespace using SCI_SETWHITESPACESIZE. + Feature #2839427. +
  • +
  • + Additional carets can be hidden with SCI_SETADDITIONALCARETSVISIBLE. +
  • +
  • + Can choose anti-aliased, non-anti-aliased or lcd-optimized text using SCI_SETFONTQUALITY. +
  • +
  • + Retrieve the current selected text in the autocompletion list with SCI_AUTOCGETCURRENTTEXT. +
  • +
  • + Retrieve the name of the current lexer with SCI_GETLEXERLANGUAGE. +
  • +
  • + Progress 4GL lexer improves handling of comments in preprocessor declaration. + Feature #2902206. +
  • +
  • + HTML lexer extended to handle Mako template language. +
  • +
  • + SQL folder extended for SQL Anywhere "EXISTS" and "ENDIF" keywords. + Feature #2887524. +
  • +
  • + SciTE adds APIPath and AbbrevPath variables. +
  • +
  • + SciTE on GTK+ uses pipes instead of temporary files for running tools. This should be more secure. +
  • +
  • + Fixed crash when calling SCI_STYLEGETFONT for a style which does not have a font set. + Bug #2857425. +
  • +
  • + Fixed crash caused by not having sufficient styles allocated after choosing a lexer. + Bug #2881279. +
  • +
  • + Fixed crash in SciTE using autocomplete word when word characters includes space. + Bug #2840141. +
  • +
  • + Fixed bug with handling upper-case file extensions SciTE on GTK+. +
  • +
  • + Fixed SciTE loading files from sessions with folded folds where it would not + be scrolled to the correct location. + Bug #2882775. +
  • +
  • + Fixed SciTE loading files from sessions when file no longer exists. + Bug #2883437. +
  • +
  • + Fixed SciTE export to HTML using the wrong background colour. +
  • +
  • + Fixed crash when adding an annotation and then adding a new line after the annotation. + Bug #2929708. +
  • +
  • + Fixed crash in SciTE setting a property to nil from Lua. +
  • +
  • + SCI_GETSELTEXT fixed to return correct length. + Bug #2929441. +
  • +
  • + Fixed text positioning problems with selection in some circumstances. +
  • +
  • + Fixed text positioning problems with ligatures on GTK+. +
  • +
  • + Fixed problem pasting into rectangular selection with caret at bottom caused text to go from the caret down + rather than replacing the selection. +
  • +
  • + Fixed problem replacing in a rectangular selection where only the final line was changed. +
  • +
  • + Fixed inability to select a rectangular area using Alt+Shift+Click at both corners. + Bug #2899746. +
  • +
  • + Fixed problem moving to start/end of a rectangular selection with left/right key. + Bug #2871358. +
  • +
  • + Fixed problem with Select All when there's a rectangular selection. + Bug #2930488. +
  • +
  • + Fixed SCI_LINEDUPLICATE on a rectangular selection to not produce multiple discontinuous selections. +
  • +
  • + Virtual space removed when performing delete word left or delete line left. + Virtual space converted to real space for delete word right. + Preserve virtual space when pressing Delete key. + Bug #2882566. +
  • +
  • + Fixed problem where Shift+Alt+Down did not move through wrapped lines. + Bug #2871749. +
  • +
  • + Fixed incorrect background colour when using coloured lines with virtual space. + Bug #2914691. +
  • +
  • + Fixed failure to display wrap symbol for SC_WRAPVISUALFLAGLOC_END_BY_TEXT. + Bug #2936108. +
  • +
  • + Fixed blank background colour with EOLFilled style on last line. + Bug #2890105. +
  • +
  • + Fixed problem in VB lexer with keyword at end of file. + Bug #2901239. +
  • +
  • + Fixed SciTE bug where double clicking on a tab closed the file. +
  • +
  • + Fixed SciTE brace matching commands to only work when the caret is next to the brace, not when + it is in virtual space. + Bug #2885560. +
  • +
  • + Fixed SciTE on Windows Vista to access files in the Program Files directory rather than allow Windows + to virtualize access. + Bug #2916685. +
  • +
  • + Fixed NSIS folder to handle keywords that start with '!'. + Bug #2872157. +
  • +
  • + Changed linkage of Scintilla_LinkLexers to "C" so that it can be used by clients written in C. + Bug #2844718. +
  • +
+

+ Release 2.01 +

+
    +
  • + Released on 19 August 2009. +
  • +
  • + Fix to positioning rectangular paste when viewing line ends. +
  • +
  • + Don't insert new lines and indentation for line ends at end of rectangular paste. +
  • +
  • + When not in additional selection typing mode, cutting a rectangular selection removes all of the selected text. +
  • +
  • + Rectangular selections are copied to the clipboard in document order, not in the order of selection. +
  • +
  • + SCI_SETCURRENTPOS and SCI_SETANCHOR work in rectangular mode. +
  • +
  • + On GTK+, drag and drop to a later position in the document now drops at the position. +
  • +
  • + Fix bug where missing property did not use default value. +
  • +
+

+ Release 2.0 +

+
    +
  • + Released on 11 August 2009. +
  • +
  • + Multiple pieces of text can be selected simultaneously by holding control while dragging the mouse. + Typing, backspace and delete may affect all selections together. +
  • +
  • + Virtual space allows selecting beyond the last character on a line. +
  • +
  • + SciTE on GTK+ path bar is now optional and defaults to off. +
  • +
  • + MagikSF lexer recognizes numbers correctly. +
  • +
  • + Folding of Python comments and blank lines improved. Bug #210240. +
  • +
  • + Bug fixed where background colour of last character in document leaked past that character. +
  • +
  • + Crash fixed when adding marker beyond last line in document. Bug #2830307. +
  • +
  • + Resource leak fixed in SciTE for Windows when printing fails. Bug #2816524. +
  • +
  • + Bug fixed on Windows where the system caret was destroyed during destruction when another window + was using the system caret. Bug #2830223. +
  • +
  • + Bug fixed where indentation guides were drawn over text when the indentation used a style with a different + space width to the default style. +
  • +
  • + SciTE bug fixed where box comment added a bare line feed rather than the chosen line end. Bug #2818104. +
  • +
  • + Reverted fix that led to wrapping whole document when displaying the first line of the document. +
  • +
  • + Export to LaTeX in SciTE fixed to work in more cases and not use as much space. Bug #1286548. +
  • +
  • + Bug fixed where EN_CHANGE notification was sent when performing a paste operation in a + read-only document. Bug #2825485. +
  • +
  • + Refactored code so that Scintilla exposes less of its internal implementation and uses the C++ standard + library for some basic collections. Projects that linked to Scintilla's SString or PropSet classes + should copy this code from a previous version of Scintilla or from SciTE. +
  • +
+

+ Release 1.79 +

+
    +
  • + Released on 1 July 2009. +
  • +
  • + Memory exhaustion and other exceptions handled by placing an error value into the + status property rather than crashing. + Scintilla now builds with exception handling enabled and requires exception handling to be enabled.
    + This is a major change and application developers should consider how they will deal with Scintilla exhausting + memory since Scintilla may not be in a stable state. +
  • +
  • + Deprecated APIs removed. The symbols removed are: +
      +
    • SCI_SETCARETPOLICY
    • +
    • CARET_CENTER
    • +
    • CARET_XEVEN
    • +
    • CARET_XJUMPS
    • +
    • SC_FOLDFLAG_BOX
    • +
    • SC_FOLDLEVELBOXHEADERFLAG
    • +
    • SC_FOLDLEVELBOXFOOTERFLAG
    • +
    • SC_FOLDLEVELCONTRACTED
    • +
    • SC_FOLDLEVELUNINDENT
    • +
    • SCN_POSCHANGED
    • +
    • SCN_CHECKBRACE
    • +
    • SCLEX_ASP
    • +
    • SCLEX_PHP
    • +
    +
  • +
  • + Cocoa platform added. +
  • +
  • + Names of struct types in Scintilla.h now start with "Sci_" to avoid possible clashes with platform + definitions. Currently, the old names still work but these will be phased out. +
  • +
  • + When lines are wrapped, subsequent lines may be indented to match the indent of the initial line, + or one more indentation level. Feature #2796119. +
  • +
  • + APIs added for finding the character at a point rather than an inter-character position. Feature #2646738. +
  • +
  • + A new marker SC_MARK_BACKGROUND_UNDERLINE is drawn in the text area as an underline + the full width of the window. +
  • +
  • + Batch file lexer understands variables surrounded by '!'. +
  • +
  • + CAML lexer also supports SML. +
  • +
  • + D lexer handles string and numeric literals more accurately. Feature #2793782. +
  • +
  • + Forth lexer is now case-insensitive and better supports numbers like $hex and %binary. Feature #2804894. +
  • +
  • + Lisp lexer treats '[', ']', '{', and '}' as balanced delimiters which is common usage. Feature #2794989. +
    + It treats keyword argument names as being equivalent to symbols. Feature #2794901. +
  • +
  • + Pascal lexer bug fixed to prevent hang when 'interface' near beginning of file. Bug #2802863. +
  • +
  • + Perl lexer bug fixed where previous lexical states persisted causing "/" special case styling and + subroutine prototype styling to not be correct. Bug #2809168. +
  • +
  • + XML lexer fixes bug where Unicode entities like '&—' were broken into fragments. Bug #2804760. +
  • +
  • + SciTE on GTK+ enables scrolling the tab bar on recent versions of GTK+. Feature #2061821. +
  • +
  • + SciTE on Windows allows tab bar tabs to be reordered by drag and drop. +
  • +
  • + Unit test script for Scintilla on Windows included with source code. +
  • +
  • + User defined menu items are now localized when there is a matching translation. +
  • +
  • + Width of icon column of autocompletion lists on GTK+ made more consistent. +
  • +
  • + Bug with slicing UTF-8 text into character fragments when there is a sequence of 100 or more 3 byte characters. Bug #2780566. +
  • +
  • + Folding bugs introduced in 1.78 fixed. Some of the fix was generic and there was also a specific fix for C++. +
  • +
  • + Bug fixed where a rectangular paste was not padding the line with sufficient spaces to align the pasted text. +
  • +
  • + Bug fixed with showing all text on each line of multi-line annotations when styling the whole annotation using SCI_ANNOTATIONSETSTYLE. Bug #2789430. +
  • +
+

+ Release 1.78 +

+
    +
  • + Released on 28 April 2009. +
  • +
  • + Annotation lines may be added to each line. +
  • +
  • + A text margin may be defined with different text on each line. +
  • +
  • + Application actions may be added to the undo history. +
  • +
  • + Can query the symbol defined for a marker. + An available symbol added for applications to indicate that plugins may allocate a marker. +
  • +
  • + Can increase the amount of font ascent and descent. +
  • +
  • + COBOL lexer added. Feature #2127406. +
  • +
  • + Nimrod lexer added. Feature #2642620. +
  • +
  • + PowerPro lexer added. Feature #2195308. +
  • +
  • + SML lexer added. Feature #2710950. +
  • +
  • + SORCUS Installation file lexer added. Feature #2343375. +
  • +
  • + TACL lexer added. Feature #2127406. +
  • +
  • + TAL lexer added. Feature #2127406. +
  • +
  • + Rewritten Pascal lexer with improved folding and other fixes. Feature #2190650. +
  • +
  • + INDIC_ROUNDBOX translucency level can be modified. Feature #2586290. +
  • +
  • + C++ lexer treats angle brackets in #include directives as quotes when styling.within.preprocessor. Bug #2551033. +
  • +
  • + Inno Setup lexer is sensitive to whether within the [Code] section and handles comments better. Bug #2552973. +
  • +
  • + HTML lexer does not go into script mode when script tag is self-closing. +
  • +
  • + HTML folder fixed where confused by comments when fold.html.preprocessor off. Bug #2532774. +
  • +
  • + Perl lexer fixes problem with string matching caused by line endings. Bug #2648342. +
  • +
  • + Progress lexer fixes problem with "last-event:function" phrase. Bug #2483619. +
  • +
  • + Properties file lexer extended to handle RFC2822 text when lexer.props.allow.initial.spaces on. +
  • +
  • + Python lexer adds options for Python 3 and Cython. +
  • +
  • + Shell lexer fixes heredoc problem caused by line endings. Bug #2635257. +
  • +
  • + TeX lexer handles comment at end of line correctly. Bug #2698766. +
  • +
  • + SciTE retains selection range when performing a replace selection command. Feature #2339160. +
  • +
  • + SciTE definition of word characters fixed to match documentation. Bug #2464531. +
  • +
  • + SciTE on GTK+ performing Search or Replace when dialog already shown now brings dialog to foreground. + Bug #2634224. +
  • +
  • + Fixed encoding bug with calltips on GTK+. +
  • +
  • + Block caret drawn in correct place on wrapped lines. Bug #2126144. +
  • +
  • + Compilation for 64 bit Windows works using MinGW. Bug #2515578. +
  • +
  • + Incorrect memory freeing fixed on OS X. + Bug #2354098, + Bug #2671749. +
  • +
  • + SciTE on GTK+ crash fixed on startup when child process exits before initialization complete. + Bug #2716987. +
  • +
  • + Crash fixed when AutoCompleteGetCurrent called with no active autocompletion. +
  • +
  • + Flickering diminished when pressing Tab. Bug #2723006. +
  • +
  • + Namespace compilation issues with GTK+ on OS X fixed. +
  • +
  • + Increased maximum length of SciTE's Language menu on GTK+ to 100 items. Bug #2528241. +
  • +
  • + Fixed incorrect Python lexing for multi-line continued strings. Bug #2450963. +
  • +
+

+ Release 1.77 +

+
    +
  • + Released on 18 October 2008. +
  • +
  • + Direct temporary access to Scintilla's text buffer to allow simple efficient interfacing + to libraries like regular expression libraries. +
  • +
  • + Scintilla on Windows can interpret keys as Unicode even when a narrow character + window with SCI_SETKEYSUNICODE. +
  • +
  • + Notification sent when autocompletion cancelled. +
  • +
  • + MySQL lexer added. +
  • +
  • + Lexer for gettext .po files added. +
  • +
  • + Abaqus lexer handles program structure more correctly. +
  • +
  • + Assembler lexer works with non-ASCII text. +
  • +
  • + C++ lexer allows mixed case doc comment tags. +
  • +
  • + CSS lexer updated and works with non-ASCII. +
  • +
  • + Diff lexer adds style for changed lines, handles subversion diffs better and + fixes styling and folding for lines containing chunk dividers ("---"). +
  • +
  • + FORTRAN lexer accepts more styles of compiler directive. +
  • +
  • + Haskell lexer allows hexadecimal literals. +
  • +
  • + HTML lexer improves PHP and JavaScript folding. + PHP heredocs, nowdocs, strings and comments processed more accurately. + Internet Explorer's non-standard >comment< tag supported. + Script recognition in XML can be controlled with lexer.xml.allow.scripts property. +
  • +
  • + Lua lexer styles last character correctly. +
  • +
  • + Perl lexer update. +
  • +
  • + Comment folding implemented for Ruby. +
  • +
  • + Better TeX folding. +
  • +
  • + Verilog lexer updated. +
  • +
  • + Windows Batch file lexer handles %~ and %*. +
  • +
  • + YAML lexer allows non-ASCII text. +
  • +
  • + SciTE on GTK+ implements "Replace in Buffers" in advanced mode. +
  • +
  • + The extender OnBeforeSave method can override the default file saving behaviour by retuning true. +
  • +
  • + Window position and recent files list may be saved into the session file. +
  • +
  • + Right button press outside the selection moves the caret. +
  • +
  • + SciTE load.on.activate works when closing a document reveals a changed document. +
  • +
  • + SciTE bug fixed where eol.mode not used for initial buffer. +
  • +
  • + SciTE bug fixed where a file could be saved as the same name as another + buffer leading to confusing behaviour. +
  • +
  • + Fixed display bug for long lines in same style on Windows. +
  • +
  • + Fixed SciTE crash when finding matching preprocessor command used on some files. +
  • +
  • + Drawing performance improved for files with many blank lines. +
  • +
  • + Folding bugs fixed where changing program text produced a decrease in fold level on a fold header line. +
  • +
  • + Clearing document style now clears all indicators. +
  • +
  • + SciTE's embedded Lua updated to 5.1.4. +
  • +
  • + SciTE will compile with versions of GTK+ before 2.8 again. +
  • +
  • + SciTE on GTK+ bug fixed where multiple files not opened. +
  • +
  • + Bug fixed with SCI_VCHOMEWRAP and SCI_VCHOMEWRAPEXTEND on white last line. +
  • +
  • + Regular expression bug fixed where "^[^(]+$" matched empty lines. +
  • +
+

+ Release 1.76 +

+
    +
  • + Released on 16 March 2008. +
  • +
  • + Support for PowerShell. +
  • +
  • + Lexer added for Magik. +
  • +
  • + Director extension working on GTK+. +
  • +
  • + Director extension may set focus to SciTE through "focus:" message on GTK+. +
  • +
  • + C++ folder handles final line better in some cases. +
  • +
  • + SCI_COPYALLOWLINE added which is similar to SCI_COPY except that if the selection is empty then + the line holding the caret is copied. On Windows an extra clipboard format allows pasting this as a whole + line before the current selection. This behaviour is compatible with Visual Studio. +
  • +
  • + On Windows, the horizontal scroll bar can handle wider files. +
  • +
  • + On Windows, a system palette leak was fixed. Should not affect many as palette mode is rarely used. +
  • +
  • + Install command on GTK+ no longer tries to set explicit owner. +
  • +
  • + Perl lexer handles defined-or operator "//". +
  • +
  • + Octave lexer fixes "!=" operator. +
  • +
  • + Optimized selection change drawing to not redraw as much when not needed. +
  • +
  • + SciTE on GTK+ no longer echoes Lua commands so is same as on Windows. +
  • +
  • + Automatic vertical scrolling limited to one line at a time so is not too fast. +
  • +
  • + Crash fixed when line states set beyond end of line states. This occurred when lexers did not + set a line state for each line. +
  • +
  • + Crash in SciTE on Windows fixed when search for 513 character string fails. +
  • +
  • + SciTE disables translucent features on Windows 9x due to crashes reported when using translucency. +
  • +
  • + Bug fixed where whitespace background was not seen on wrapped lines. +
  • +
+

+ Release 1.75 +

+
    +
  • + Released on 22 November 2007. +
  • +
  • + Some WordList and PropSet functionality moved from Scintilla to SciTE. + Projects that link to Scintilla's code for these classes may need to copy + code from SciTE. +
  • +
  • + Borland C++ can no longer build Scintilla. +
  • +
  • + Invalid bytes in UTF-8 mode are displayed as hex blobs. This also prevents crashes due to + passing invalid UTF-8 to platform calls. +
  • +
  • + Indentation guides enhanced to be visible on completely empty lines when possible. +
  • +
  • + The horizontal scroll bar may grow to match the widest line displayed. +
  • +
  • + Allow autocomplete pop ups to appear outside client rectangle in some cases. +
  • +
  • + When line state changed, SC_MOD_CHANGELINESTATE modification notification sent and + margin redrawn. +
  • +
  • + SciTE scripts can access the menu command values IDM_*. +
  • +
  • + SciTE's statement.end property has been implemented again. +
  • +
  • + SciTE shows paths and matches in different styles for Find In Files. +
  • +
  • + Incremental search in SciTE for Windows is modeless to make it easier to exit. +
  • +
  • + Folding performance improved. +
  • +
  • + SciTE for GTK+ now includes a Browse button in the Find In Files dialog. +
  • +
  • + On Windows versions that support Unicode well, Scintilla is a wide character window + which allows input for some less common languages like Armenian, Devanagari, + Tamil, and Georgian. To fully benefit, applications should use wide character calls. +
  • +
  • + Lua function names are exported from SciTE to allow some extension libraries to work. +
  • +
  • + Lexers added for Abaqus, Ansys APDL, Asymptote, and R. +
  • +
  • + SCI_DELWORDRIGHTEND added for closer compatibility with GTK+ entry widget. +
  • +
  • + The styling buffer may now use all 8 bits in each byte for lexical states with 0 bits for indicators. +
  • +
  • + Multiple characters may be set for SciTE's calltip.<lexer>.parameters.start property. +
  • +
  • + Bash lexer handles octal literals. +
  • +
  • + C++/JavaScript lexer recognizes regex literals in more situations. +
  • +
  • + Haskell lexer fixed for quoted strings. +
  • +
  • + HTML/XML lexer does not notice XML indicator if there is + non-whitespace between the "<?" and "XML". + ASP problem fixed where </ is used inside a comment. +
  • +
  • + Error messages from Lua 5.1 are recognized. +
  • +
  • + Folding implemented for Metapost. +
  • +
  • + Perl lexer enhanced for handling minus-prefixed barewords, + underscores in numeric literals and vector/version strings, + ^D and ^Z similar to __END__, + subroutine prototypes as a new lexical class, + formats and format blocks as new lexical classes, and + '/' suffixed keywords and barewords. +
  • +
  • + Python lexer styles all of a decorator in the decorator style rather than just the name. +
  • +
  • + YAML lexer styles colons as operators. +
  • +
  • + Fixed SciTE bug where undo would group together multiple separate modifications. +
  • +
  • + Bug fixed where setting background colour of calltip failed. +
  • +
  • + SciTE allows wildcard suffixes for file pattern based properties. +
  • +
  • + SciTE on GTK+ bug fixed where user not prompted to save untitled buffer. +
  • +
  • + SciTE bug fixed where property values from one file were not seen by lower priority files. +
  • +
  • + Bug fixed when showing selection with a foreground colour change which highlighted + an incorrect range in some positions. +
  • +
  • + Cut now invokes SCN_MODIFYATTEMPTRO notification. +
  • +
  • + Bug fixed where caret not shown at beginning of wrapped lines. + Caret made visible in some cases after wrapping and scroll bar updated after wrapping. +
  • +
  • + Modern indicators now work on wrapped lines. +
  • +
  • + Some crashes fixed for 64-bit GTK+. +
  • +
  • + On GTK+ clipboard features improved for VMWare tools copy and paste. + SciTE exports the clipboard more consistently on shut down. +
  • +
+

+ Release 1.74 +

+
    +
  • + Released on 18 June 2007. +
  • +
  • + OS X support. +
  • +
  • + Indicators changed to be a separate data structure allowing more indicators. Storing indicators in high bits + of styling bytes is deprecated and will be removed in the next version. +
  • +
  • + Unicode support extended to all Unicode characters not just the Basic Multilingual Plane. +
  • +
  • + Performance improved on wide lines by breaking long runs in a single style into shorter segments. +
  • +
  • + Performance improved by caching layout of short text segments. +
  • +
  • + SciTE includes Lua 5.1. +
  • +
  • + Caret may be displayed as a block. +
  • +
  • + Lexer added for GAP. +
  • +
  • + Lexer added for PL/M. +
  • +
  • + Lexer added for Progress. +
  • +
  • + SciTE session files have changed format to be like other SciTE .properties files + and now use the extension .session. + Bookmarks and folds may optionally be saved in session files. + Session files created with previous versions of SciTE will not load into this version. +
  • +
  • + SciTE's extension and scripting interfaces add OnKey, OnDwellStart, and OnClose methods. +
  • +
  • + On GTK+, copying to the clipboard does not include the text/urilist type since this caused problems when + pasting into Open Office. +
  • +
  • + On GTK+, Scintilla defaults caret blink rate to platform preference. +
  • +
  • + Dragging does not start until the mouse has been dragged a certain amount. + This stops spurious drags when just clicking inside the selection. +
  • +
  • + Bug fixed where brace highlight not shown when caret line background set. +
  • +
  • + Bug fixed in Ruby lexer where out of bounds access could occur. +
  • +
  • + Bug fixed in XML folding where tags were not being folded because they are singletons in HTML. +
  • +
  • + Bug fixed when many font names used. +
  • +
  • + Layout bug fixed on GTK+ where fonts have ligatures available. +
  • +
  • + Bug fixed with SCI_LINETRANSPOSE on a blank line. +
  • +
  • + SciTE hang fixed when using UNC path with directory properties feature. +
  • +
  • + Bug on Windows fixed by examining dropped text for Unicode even in non-Unicode mode so it + can work when source only provides Unicode or when using an encoding different from the + system default. +
  • +
  • + SciTE bug on GTK+ fixed where Stop Executing did not work when more than a single process started. +
  • +
  • + SciTE bug on GTK+ fixed where mouse wheel was not switching between buffers. +
  • +
  • + Minor line end fix to PostScript lexer. +
  • +
+

+ Release 1.73 +

+
    +
  • + Released on 31 March 2007. +
  • +
  • + SciTE adds a Directory properties file to configure behaviour for files in a directory and its subdirectories. +
  • +
  • + Style changes may be made during text modification events. +
  • +
  • + Regular expressions recognize \d, \D, \s, \S, \w, \W, and \xHH. +
  • +
  • + Support for cmake language added. +
  • +
  • + More Scintilla properties can be queried. +
  • +
  • + Edge line drawn under text. +
  • +
  • + A savesession command added to SciTE director interface. +
  • +
  • + SciTE File | Encoding menu item names changed to be less confusing. +
  • +
  • + SciTE on GTK+ dialog buttons reordered to follow guidelines. +
  • +
  • + SciTE on GTK+ removed GTK+ 1.x compatible file dialog code. +
  • +
  • + SciTE on GTK+ recognizes key names KeypadMultiply and KeypadDivide. +
  • +
  • + Background colour of line wrapping visual flag changed to STYLE_DEFAULT. +
  • +
  • + Makefile lexing enhanced for ':=' operator and when lines start with tab. +
  • +
  • + TADS3 lexer and folder improved. +
  • +
  • + SCN_DOUBLECLICK notification may set SCI_SHIFT, SCI_CTRL, and SCI_ALT flags on modifiers field. +
  • +
  • + Slow folding of large constructs in Python fixed. +
  • +
  • + MSSQL folding fixed to be case-insensitive and fold at more keywords. +
  • +
  • + SciTE's brace matching works better for HTML. +
  • +
  • + Determining API list items checks for specified parameters start character before default '('. +
  • +
  • + Hang fixed in HTML lexer. +
  • +
  • + Bug fixed in with LineTranspose command where markers could move to different line. +
  • +
  • + Memory released when buffer completely emptied. +
  • +
  • + If translucency not available on Windows, draw rectangular outline instead. +
  • +
  • + Bash lexer handles "-x" in "--x-includes..." better. +
  • +
  • + AutoIt3 lexer fixes string followed by '+'. +
  • +
  • + LinesJoin fixed where it stopped early due to not adjusting for inserted spaces.. +
  • +
  • + StutteredPageDown fixed when lines wrapped. +
  • +
  • + FormatRange fixed to not double count line number width which could lead to a large space. +
  • +
  • + SciTE Export As PDF and Latex commands fixed to format floating point numbers with '.' even in locales + that use ','. +
  • +
  • + SciTE bug fixed where File | New could produce buffer with contents of previous file when using read-only mode. +
  • +
  • + SciTE retains current scroll position when switching buffers and fold.on.open set. +
  • +
  • + SciTE crash fixed where '*' used to invoke parameters dialog. +
  • +
  • + SciTE bugs when writing large UCS-2 files fixed. +
  • +
  • + Bug fixed when scrolling inside a SCN_PAINTED event by invalidating window + rather than trying to perform synchronous painting. +
  • +
  • + SciTE for GTK+ View | Full Screen works on recent versions of GTK+. +
  • +
  • + SciTE for Windows enables and disables toolbar commands correctly. +
  • +
+

+ Release 1.72 +

+
    +
  • + Released on 15 January 2007. +
  • +
  • + Performance of per-line data improved. +
  • +
  • + SC_STARTACTION flag set on the first modification notification in an undo + transaction to help synchronize the container's undo stack with Scintilla's. +
  • +
  • + On GTK+ drag and drop defaults to move rather than copy. +
  • +
  • + Scintilla supports extending appearance of selection to right hand margin. +
  • +
  • + Incremental search available on GTK+. +
  • +
  • + SciTE Indentation Settings dialog available on GTK+ and adds a "Convert" button. +
  • +
  • + Find in Files can optionally ignore binary files or directories that start with ".". +
  • +
  • + Lexer added for "D" language. +
  • +
  • + Export as HTML shows folding with underline lines and +/- symbols. +
  • +
  • + Ruby lexer interprets interpolated strings as expressions. +
  • +
  • + Lua lexer fixes some cases of numeric literals. +
  • +
  • + C++ folder fixes bug with "@" in doc comments. +
  • +
  • + NSIS folder handles !if and related commands. +
  • +
  • + Inno setup lexer adds styling for single and double quoted strings. +
  • +
  • + Matlab lexer handles backslashes in string literals correctly. +
  • +
  • + HTML lexer fixed to allow "?>" in comments in Basic script. +
  • +
  • + Added key codes for Windows key and Menu key. +
  • +
  • + Lua script method scite.MenuCommand(x) performs a menu command. +
  • +
  • + SciTE bug fixed with box comment command near start of file setting selection to end of file. +
  • +
  • + SciTE on GTK+, fixed loop that occurred with automatic loading for an unreadable file. +
  • +
  • + SciTE asks whether to save files when Windows shuts down. +
  • +
  • + Save Session on Windows now defaults the extension to "ses". +
  • +
  • + Bug fixed with single character keywords. +
  • +
  • + Fixed infinite loop for SCI_GETCOLUMN for position beyond end of document. +
  • +
  • + Fixed failure to accept typing on Solaris/GTK+ when using default ISO-8859-1 encoding. +
  • +
  • + Fixed warning from Lua in SciTE when creating a new buffer when already have + maximum number of buffers open. +
  • +
  • + Crash fixed with "%%" at end of batch file. +
  • +
+

+ Release 1.71 +

+
    +
  • + Released on 21 August 2006. +
  • + +
  • + Double click notification includes line and position. +
  • +
  • + VB lexer bugs fixed for preprocessor directive below a comment or some other states and + to use string not closed style back to the starting quote when there are internal doubled quotes. +
  • +
  • + C++ lexer allows identifiers to contain '$' and non-ASCII characters such as UTF-8. + The '$' character can be disallowed with lexer.cpp.allow.dollars=0. +
  • +
  • + Perl lexer allows UTF-8 identifiers and has some other small improvements. +
  • +
  • + SciTE's $(CurrentWord) uses word.characters.<filepattern> to define the word + rather than a hardcoded list of word characters. +
  • +
  • + SciTE Export as HTML adds encoding information for UTF-8 file and fixes DOCTYPE. +
  • +
  • + SciTE session and .recent files default to the user properties directory rather than global + properties directory. +
  • +
  • + Left and right scroll events handled correctly on GTK+ and horizontal scroll bar has more sensible + distances for page and arrow clicks. +
  • +
  • + SciTE on GTK+ tab bar fixed to work on recent versions of GTK+. +
  • +
  • + On GTK+, if the approximate character set conversion is unavailable, a second attempt is made + without approximations. This may allow keyboard input and paste to work on older systems. +
  • +
  • + SciTE on GTK+ can redefine the Insert key. +
  • +
  • + SciTE scripting interface bug fixed where some string properties could not be changed. +
  • +
+

+ Release 1.70 +

+
    +
  • + Released on 20 June 2006. +
  • +
  • + On GTK+, character set conversion is performed using an option that allows approximate conversions rather + than failures when a character can not be converted. This may lead to similar characters being inserted or + when no similar character is available a '?' may be inserted. +
  • +
  • + On GTK+, the internationalized IM (Input Method) feature is used for all typed input for all character sets. +
  • +
  • + Scintilla has new margin types SC_MARGIN_BACK and SC_MARGIN_FORE that use the default + style's background and foreground colours (normally white and black) as the background to the margin. +
  • +
  • + Scintilla/GTK+ allows file drops on Windows when drop is of type DROPFILES_DND + as well as text/uri-list. +
  • +
  • + Code page can only be set to one of the listed valid values. +
  • +
  • + Text wrapping fixed for cases where insertion was not wide enough to trigger + wrapping before being styled but was after styling. +
  • +
  • + SciTE find marks are removed before printing or exporting to avoid producing incorrect styles. +
  • +
+

+ Release 1.69 +

+
    +
  • + Released on 29 May 2006. +
  • +
  • + SciTE supports z-order based buffer switching on Ctrl+Tab. +
  • +
  • + Translucent support for selection and whole line markers. +
  • +
  • + SciTE may have per-language abbreviations files. +
  • +
  • + Support for Spice language. +
  • +
  • + On GTK+ autocompletion lists are optimized and use correct selection colours. +
  • +
  • + On GTK+ the URI data type is preferred in drag and drop so that applications + will see files dragged from the shell rather than dragging the text of the file name + into the document. +
  • +
  • + Increased number of margins to 5. +
  • +
  • + Basic lexer allows include directive $include: "file name". +
  • +
  • + SQL lexer no longer bases folding on indentation. +
  • +
  • + Line ends are transformed when copied to clipboard on + Windows/GTK+2 as well as Windows/GTK+ 1. +
  • +
  • + Lexing code masks off the indicator bits on the start style before calling the lexer + to avoid confusing the lexer when an application has used an indicator. +
  • +
  • + SciTE savebefore:yes only saves the file when it has been changed. +
  • +
  • + SciTE adds output.initial.hide setting to allow setting the size of the output pane + without it showing initially. +
  • +
  • + SciTE on Windows Go To dialog allows line number with more digits. +
  • +
  • + Bug in HTML lexer fixed where a segment of PHP could switch scripting language + based on earlier text on that line. +
  • +
  • + Memory bug fixed when freeing regions on GTK+. + Other minor bugs fixed on GTK+. +
  • +
  • + Deprecated GTK+ calls in Scintilla replaced with current calls. +
  • +
  • + Fixed a SciTE bug where closing the final buffer, if read-only, left the text present in an + untitled buffer. +
  • +
  • + Bug fixed in bash lexer that prevented folding. +
  • +
  • + Crash fixed in bash lexer when backslash at end of file. +
  • +
  • + Crash on recent releases of GTK+ 2.x avoided by changing default font from X + core font to Pango font "!Sans". +
  • +
  • + Fix for SciTE properties files where multiline properties continued over completely blank lines. +
  • +
  • + Bug fixed in SciTE/GTK+ director interface where more data available than + buffer size. +
  • +
  • + Minor visual fixes to SciTE splitter on GTK+. +
  • +
+

+ Release 1.68 +

+
    +
  • + Released on 9 March 2006. +
  • +
  • + Translucent drawing implemented for caret line and box indicators. +
  • +
  • + Lexer specifically for TCL is much more accurate than reusing C++ lexer. +
  • +
  • + Support for Inno Setup scripts. +
  • +
  • + Support for Opal language. +
  • +
  • + Calltips may use a new style, STYLE_CALLTIP which allows choosing a + different font for calltips. +
  • +
  • + Python lexer styles comments on decorators. +
  • +
  • + HTML lexer refined handling of "?>" and "%>" within server + side scripts. +
  • +
  • + Batch file lexer improved. +
  • +
  • + Eiffel lexer doesn't treat '.' as a name character. +
  • +
  • + Lua lexer handles length operator, #, and hex literals. +
  • +
  • + Properties file lexer has separate style for keys. +
  • +
  • + PL/SQL folding improved. +
  • +
  • + SciTE Replace dialog always searches in forwards direction. +
  • +
  • + SciTE can detect language of file from initial #! line. +
  • +
  • + SciTE on GTK+ supports output.scroll=2 setting. +
  • +
  • + SciTE can perform an import a properties file from the command line. +
  • +
  • + Set of word characters used for regular expression \< and \>. +
  • +
  • + Bug fixed with SCI_COPYTEXT stopping too early. +
  • +
  • + Bug fixed with splitting lines so that all lines are split. +
  • +
  • + SciTE calls OnSwitchFile when closing one buffer causes a switch to another. +
  • +
  • + SciTE bug fixed where properties were being reevaluated without good reason + after running a macro. +
  • +
  • + Crash fixed when clearing document with some lines contracted in word wrap mode. +
  • +
  • + Palette expands as more entries are needed. +
  • +
  • + SCI_POSITIONFROMPOINT returns more reasonable value when close to + last text on a line. +
  • +
  • + On Windows, long pieces of text may be drawn in segments if they fail to draw + as a whole. +
  • +
  • + Bug fixed with bad drawing when some visual changes made inside SCN_UPDATEUI + notification. +
  • +
  • + SciTE bug fixed with groupundo setting. +
  • +
+

+ Release 1.67 +

+
    +
  • + Released on 17 December 2005. +
  • +
  • + Scintilla checks the paint region more accurately when seeing if an area is being + repainted. Platform layer implementations may need to change for this to take + effect. This fixes some drawing and styling bugs. Also optimized some parts of + marker code to only redraw the line of the marker rather than whole of the margin. +
  • +
  • + Quoted identifier style for SQL. SQL folding performed more simply. +
  • +
  • + Ruby lexer improved to better handle here documents and non-ASCII + characters. +
  • +
  • + Lua lexer supports long string and block comment syntax from Lua 5.1. +
  • +
  • + Bash lexer handles here documents better. +
  • +
  • + JavaScript lexing recognizes regular expressions more accurately and includes flag + characters in the regular expression style. This is both in JavaScript files and when + JavaScript is embedded in HTML. +
  • +
  • + Scintilla API provided to reveal how many style bits are needed for the + current lexer. +
  • +
  • + Selection duplicate added. +
  • +
  • + Scintilla API for adding a set of markers to a line. +
  • +
  • + DBCS encodings work on Windows 9x. +
  • +
  • + Convention defined for property names to be used by lexers and folders + so they can be automatically discovered and forwarded from containers. +
  • +
  • + Default bookmark in SciTE changed to a blue sphere image. +
  • +
  • + SciTE stores the time of last asking for a save separately for each buffer + which fixes bugs with automatic reloading. +
  • +
  • + On Windows, pasted text has line ends converted to current preference. + GTK+ already did this. +
  • +
  • + Kid template language better handled by HTML lexer by finishing ASP Python + mode when a ?> is found. +
  • +
  • + SciTE counts number of characters in a rectangular selection correctly. +
  • +
  • + 64-bit compatibility improved. One change that may affect user code is that + the notification message header changed to include a pointer-sized id field + to match the current Windows definition. +
  • +
  • + Empty ranges can no longer be dragged. +
  • +
  • + Crash fixed when calls made that use layout inside the painted notification. +
  • +
  • + Bug fixed where Scintilla created pixmap buffers that were too large leading + to failures when many instances used. +
  • +
  • + SciTE sets the directory of a new file to the directory of the currently + active file. +
  • +
  • + SciTE allows choosing a code page for the output pane. +
  • +
  • + SciTE HTML exporter no longer honours monospaced font setting. +
  • +
  • + Line layout cache in page mode caches the line of the caret. An assertion is + now used to ensure that the layout reentrancy problem that caused this + is easier to find. +
  • +
  • + Speed optimized for long lines and lines containing many control characters. +
  • +
  • + Bug fixed in brace matching in DBCS files where byte inside character + is same as brace. +
  • +
  • + Indent command does not indent empty lines. +
  • +
  • + SciTE bug fixed for commands that operate on files with empty extensions. +
  • +
  • + SciTE bug fixed where monospaced option was copied for subsequently opened files. +
  • +
  • + SciTE on Windows bug fixed in the display of a non-ASCII search string + which can not be found. +
  • +
  • + Bugs fixed with nested calls displaying a new calltip while one is already + displayed. +
  • +
  • + Bug fixed when styling PHP strings. +
  • +
  • + Bug fixed when styling C++ continued preprocessor lines. +
  • +
  • + SciTE bug fixed where opening file from recently used list reset choice of + language. +
  • +
  • + SciTE bug fixed when compiled with NO_EXTENSIONS and + closing one file closes the application. +
  • +
  • + SciTE crash fixed for error messages that look like Lua messages but aren't + in the same order. +
  • +
  • + Remaining fold box support deprecated. The symbols SC_FOLDLEVELBOXHEADERFLAG, + SC_FOLDLEVELBOXFOOTERFLAG, SC_FOLDLEVELCONTRACTED, + SC_FOLDLEVELUNINDENT, and SC_FOLDFLAG_BOX are deprecated. +
  • +
+

+ Release 1.66 +

+
    +
  • + Released on 26 August 2005. +
  • +
  • + New, more ambitious Ruby lexer. +
  • +
  • + SciTE Find in Files dialog has options for matching case and whole words which are + enabled when the internal find command is used. +
  • +
  • + SciTE output pane can display automatic completion after "$(" typed. + An initial ">" on a line is ignored when Enter pressed. +
  • +
  • + C++ lexer recognizes keywords within line doc comments. It continues styles over line + end characters more consistently so that eolfilled style can be used for preprocessor lines + and line comments. +
  • +
  • + VB lexer improves handling of file numbers and date literals. +
  • +
  • + Lua folder handles repeat until, nested comments and nested strings. +
  • +
  • + POV lexer improves handling of comment lines. +
  • +
  • + AU3 lexer and folder updated. COMOBJ style added. +
  • +
  • + Bug fixed with text display on GTK+ with Pango 1.8. +
  • +
  • + Caret painting avoided when not focused. +
  • +
  • + SciTE on GTK+ handles file names used to reference properties as case-sensitive. +
  • +
  • + SciTE on GTK+ Save As and Export commands set the file name field. + On GTK+ the Export commands modify the file name in the same way as on Windows. +
  • +
  • + Fixed SciTE problem where confirmation was not displaying when closing a file where all + contents had been deleted. +
  • +
  • + Middle click on SciTE tab now closes correct buffer on Windows when tool bar is visible. +
  • +
  • + SciTE bugs fixed where files contained in directory that includes '.' character. +
  • +
  • + SciTE bug fixed where import in user options was reading file from directory of + global options. +
  • +
  • + SciTE calltip bug fixed where single line calltips had arrow displayed incorrectly. +
  • +
  • + SciTE folding bug fixed where empty lines were shown for no reason. +
  • +
  • + Bug fixed where 2 byte per pixel XPM images caused crash although they are still not + displayed. +
  • +
  • + Autocompletion list size tweaked. +
  • +
+

+ Release 1.65 +

+
    +
  • + Released on 1 August 2005. +
  • +
  • + FreeBasic support. +
  • +
  • + SciTE on Windows handles command line arguments + "-" (read standard input into buffer), + "--" (read standard input into output pane) and + "-@" (read file names from standard input and open each). +
  • +
  • + SciTE includes a simple implementation of Find in Files which is used if no find.command is set. +
  • +
  • + SciTE can close tabs with a mouse middle click. +
  • +
  • + SciTE includes a save.all.for.build setting. +
  • +
  • + Folder for MSSQL. +
  • +
  • + Batch file lexer understands more of the syntax and the behaviour of built in commands. +
  • +
  • + Perl lexer handles here docs better; disambiguates barewords, quote-like delimiters, and repetition operators; + handles Pods after __END__; recognizes numbers better; and handles some typeglob special variables. +
  • +
  • + Lisp adds more lexical states. +
  • +
  • + PHP allows spaces after <<<. +
  • +
  • + TADS3 has a simpler set of states and recognizes identifiers. +
  • +
  • + Avenue elseif folds better. +
  • +
  • + Errorlist lexer treats lines starting with '+++' and '---' as separate + styles from '+' and '-' as they indicate file names in diffs. +
  • +
  • + SciTE error recognizer handles file paths in extra explanatory lines from MSVC + and in '+++' and '---' lines from diff. +
  • +
  • + Bugs fixed in SciTE and Scintilla folding behaviour when text pasted before + folded text caused unnecessary + unfolding and cutting text could lead to text being irretrievably hidden. +
  • +
  • + SciTE on Windows uses correct font for dialogs and better font for tab bar + allowing better localization +
  • +
  • + When Windows is used with a secondary monitor before the primary + monitor, autocompletion lists are not forced onto the primary monitor. +
  • +
  • + Scintilla calltip bug fixed where down arrow setting wrong value in notification + if not in first line. SciTE bug fixed where second arrow only shown on multiple line + calltip and was therefore misinterpreting the notification value. +
  • +
  • + Lexers will no longer be re-entered recursively during, for example, fold level setting. +
  • +
  • + Undo of typing in overwrite mode undoes one character at a time rather than requiring a removal + and addition step for each character. +
  • +
  • + EM_EXSETSEL(0,-1) fixed. +
  • +
  • + Bug fixed where part of a rectangular selection was not shown as selected. +
  • +
  • + Autocomplete window size fixed. +
  • +
+

+ Release 1.64 +

+
    +
  • + Released on 6 June 2005. +
  • +
  • + TADS3 support +
  • +
  • + Smalltalk support. +
  • +
  • + Rebol support. +
  • +
  • + Flagship (Clipper / XBase) support. +
  • +
  • + CSound support. +
  • +
  • + SQL enhanced to support SQL*Plus. +
  • +
  • + SC_MARK_FULLRECT margin marker fills the whole marker margin for marked + lines with a colour. +
  • +
  • + Performance improved for some large undo and redo operations and modification flags + added in notifications. +
  • +
  • + SciTE adds command equivalents for fold margin mouse actions. +
  • +
  • + SciTE adds OnUpdateUI to set of events that can be handled by a Lua script. +
  • +
  • + Properties set in Scintilla can be read. +
  • +
  • + GTK+ SciTE exit confirmation adds Cancel button. +
  • +
  • + More accurate lexing of numbers in PHP and Caml. +
  • +
  • + Perl can fold POD and package sections. POD verbatim section style. + Globbing syntax recognized better. +
  • +
  • + Context menu moved slightly on GTK+ so that it will be under the mouse and will + stay open if just clicked rather than held. +
  • +
  • + Rectangular selection paste works the same whichever direction the selection was dragged in. +
  • +
  • + EncodedFromUTF8 handles -1 length argument as documented. +
  • +
  • + Undo and redo can cause SCN_MODIFYATTEMPTRO notifications. +
  • +
  • + Indicators display correctly when they start at the second character on a line. +
  • +
  • + SciTE Export As HTML uses standards compliant CSS. +
  • +
  • + SciTE automatic indentation handles keywords for indentation better. +
  • +
  • + SciTE fold.comment.python property removed as does not work. +
  • +
  • + Fixed problem with character set conversion when pasting on GTK+. +
  • +
  • + SciTE default character set changed from ANSI_CHARSET to DEFAULT_CHARSET. +
  • +
  • + Fixed crash when creating empty autocompletion list. +
  • +
  • + Autocomplete window size made larger under some conditions to make truncation less common. +
  • +
  • + Bug fixed where changing case of a selection did not affect initial character of lines + in multi-byte encodings. +
  • +
  • + Bug fixed where rectangular selection not displayed after Alt+Shift+Click. +
  • +
+

+ Release 1.63 +

+
    +
  • + Released on 4 April 2005. +
  • +
  • + Autocompletion on Windows changed to use pop up window, be faster, + allow choice of maximum width and height, and to highlight only the text of the + selected item rather than both the text and icon if any. +
  • +
  • + Extra items can be added to the context menu in SciTE. +
  • +
  • + Character wrap mode in Scintilla helps East Asian languages. +
  • +
  • + Lexer added for Haskell. +
  • +
  • + Objective Caml support. +
  • +
  • + BlitzBasic and PureBasic support. +
  • +
  • + CSS support updated to handle CSS2. +
  • +
  • + C++ lexer is more selective about document comment keywords. +
  • +
  • + AutoIt 3 lexer improved. +
  • +
  • + Lua lexer styles end of line characters on comment and preprocessor + lines so that the eolfilled style can be applied to them. +
  • +
  • + NSIS support updated for line continuations, box comments, SectionGroup and + PageEx, and with more up-to-date properties. +
  • +
  • + Clarion lexer updated to perform folding and have more styles. +
  • +
  • + SQL lexer gains second set of keywords. +
  • +
  • + Errorlist lexer recognizes Borland Delphi error messages. +
  • +
  • + Method added for determining number of visual lines occupied by a document + line due to wrapping. +
  • +
  • + Sticky caret mode does not modify the preferred caret x position when typing + and may be useful for typing columns of text. +
  • +
  • + Dwell end notification sent when scroll occurs. +
  • +
  • + On GTK+, Scintilla requisition height is screen height rather than large fixed value. +
  • +
  • + Case insensitive autocompletion prefers exact case match. +
  • +
  • + SCI_PARADOWN and SCI_PARAUP treat lines containing only white + space as empty and handle text hidden by folding. +
  • +
  • + Scintilla on Windows supports WM_PRINTCLIENT although there are some + limitations. +
  • +
  • + SCN_AUTOCSELECTION notification sent when user selects from autoselection list. +
  • +
  • + SciTE's standard properties file sets buffers to 10, uses Pango fonts on GTK+ and + has dropped several languages to make the menu fit on screen. +
  • +
  • + SciTE's encoding cookie detection loosened so that common XML files will load + in UTF-8 if that is their declared encoding. +
  • +
  • + SciTE on GTK+ changes menus and toolbars to not be detachable unless turned + on with a property. Menus no longer tear off. The toolbar may be set to use the + default theme icons rather than SciTE's set. Changed key for View | End of Line + because of a conflict. Language menu can contain more items. +
  • +
  • + SciTE on GTK+ 2.x allows the height and width of the file open file chooser to + be set, for the show hidden files check box to be set from an option and for it + to be opened in the directory of the current file explicitly. Enter key works in + save chooser. +
  • +
  • + Scintilla lexers should no longer see bits in style bytes that are outside the set + they modify so should be able to correctly lex documents where the container + has used indicators. +
  • +
  • + SciTE no longer asks to save before performing a revert. +
  • +
  • + SciTE director interface adds a reloadproperties command to reload properties + from files. +
  • +
  • + Allow build on CYGWIN platform. +
  • +
  • + Allow use from LccWin compiler. +
  • +
  • + SCI_COLOURISE for SCLEX_CONTAINER causes a + SCN_STYLENEEDED notification. +
  • +
  • + Bugs fixed in lexing of HTML/ASP/JScript. +
  • +
  • + Fix for folding becoming confused. +
  • +
  • + On Windows, fixes for Japanese Input Method Editor and for 8 bit Katakana + characters. +
  • +
  • + Fixed buffer size bug avoided when typing long words by making buffer bigger. +
  • +
  • + Undo after automatic indentation more sensible. +
  • +
  • + SciTE menus on GTK+ uses Shift and Ctrl rather than old style abbreviations. +
  • +
  • + SciTE full screen mode on Windows calculates size more correctly. +
  • +
  • + SciTE on Windows menus work better with skinning applications. +
  • +
  • + Searching bugs fixed. +
  • +
  • + Colours reallocated when changing image using SCI_REGISTERIMAGE. +
  • +
  • + Caret stays visible when Enter held down. +
  • +
  • + Undo of automatic indentation more reasonable. +
  • +
  • + High processor usage fixed in background wrapping under some + circumstances. +
  • +
  • + Crashing bug fixed on AMD64. +
  • +
  • + SciTE crashing bug fixed when position.height or position.width not set. +
  • +
  • + Crashing bug on GTK+ fixed when setting cursor and window is NULL. +
  • +
  • + Crashing bug on GTK+ preedit window fixed. +
  • +
  • + SciTE crashing bug fixed in incremental search on Windows ME. +
  • +
  • + SciTE on Windows has an optional find and replace dialogs that can search through + all buffers and search within a particular style number. +
  • +
+

+ Release 1.62 +

+
    +
  • + Released on 31 October 2004. +
  • +
  • + Lexer added for ASN.1. +
  • +
  • + Lexer added for VHDL. +
  • +
  • + On Windows, an invisible system caret is used to allow screen readers to determine + where the caret is. The visible caret is still drawn by the painting code. +
  • +
  • + On GTK+, Scintilla has methods to read the target as UTF-8 and to convert + a string from UTF-8 to the document encoding. This eases integration with + containers that use the UTF-8 encoding which is the API encoding for GTK+ 2. +
  • +
  • + SciTE on GTK+2 and Windows NT/2000/XP allows search and replace of Unicode text. +
  • +
  • + SciTE calltips allow setting the characters used to start and end parameter lists and + to separate parameters. +
  • +
  • + FindColumn method converts a line and column into a position, taking into account + tabs and multi-byte characters. +
  • +
  • + On Windows, when Scintilla copies text to the clipboard as Unicode, it avoids + adding an ANSI copy as the system will automatically convert as required in + a context-sensitive manner. +
  • +
  • + SciTE indent.auto setting automatically determines indent.size and use.tabs from + document contents. +
  • +
  • + SciTE defines a CurrentMessage property that holds the most recently selected + output pane message. +
  • +
  • + SciTE Lua scripting enhanced with +
      +
    • A Lua table called 'buffer' is associated with each buffer and can be used to + maintain buffer-specific state.
    • +
    • A 'scite' object allows interaction with the application such as opening + files from script.
    • +
    • Dynamic properties can be reset by assigning nil to a given key in + the props table.
    • +
    • An 'OnClear' event fires whenever properties and extension scripts are + about to be reloaded.
    • +
    • On Windows, loadlib is enabled and can be used to access Lua + binary modules / DLLs.
    +
  • +
  • + SciTE Find in Files on Windows can be used in a modeless way and gains a '..' + button to move up to the parent directory. It is also wider so that longer paths + can be seen. +
  • +
  • + Close buttons added to dialogs in SciTE on Windows. +
  • +
  • + SciTE on GTK+ 2 has a "hidden files" check box in file open dialog. +
  • +
  • + SciTE use.monospaced setting removed. More information in the + FAQ. +
  • +
  • + APDL lexer updated with more lexical classes +
  • +
  • + AutoIt3 lexer updated. +
  • +
  • + Ada lexer fixed to support non-ASCII text. +
  • +
  • + Cpp lexer now only matches exactly three slashes as starting a doc-comment so that + lines of slashes are seen as a normal comment. + Line ending characters are appear in default style on preprocessor and single line + comment lines. +
  • +
  • + CSS lexer updated to support CSS2 including second set of keywords. +
  • +
  • + Errorlist lexer now understands Java stack trace lines. +
  • +
  • + SciTE's handling of HTML Tidy messages jumps to column as well as line indicated. +
  • +
  • + Lisp lexer allows multiline strings. +
  • +
  • + Lua lexer treats .. as an operator when between identifiers. +
  • +
  • + PHP lexer handles 'e' in numerical literals. +
  • +
  • + PowerBasic lexer updated for macros and optimized. +
  • +
  • + Properties file folder changed to leave lines before a header at the base level + and thus avoid a vertical line when using connected folding symbols. +
  • +
  • + GTK+ on Windows version uses Alt for rectangular selection to be compatible with + platform convention. +
  • +
  • + SciTE abbreviations file moved from system directory to user directory + so each user can have separate abbreviations. +
  • +
  • + SciTE on GTK+ has improved .desktop file and make install support that may + lead to better integration with system shell. +
  • +
  • + Disabling of themed background drawing on GTK+ extended to all cases. +
  • +
  • + SciTE date formatting on Windows performed with the user setting rather than the + system setting. +
  • +
  • + GTK+ 2 redraw while scrolling fixed. +
  • +
  • + Recursive property definitions are safer, avoiding expansion when detected. +
  • +
  • + SciTE thread synchronization for scripts no longer uses HWND_MESSAGE + so is compatible with older versions of Windows. + Other Lua scripting bugs fixed. +
  • +
  • + SciTE on Windows localization of menu accelerators changed to be compatible + with alternative UI themes. +
  • +
  • + SciTE on Windows full screen mode now fits better when menu different height + to title bar height. +
  • +
  • + SC_MARK_EMPTY marker is now invisible and does not change the background + colour. +
  • +
  • + Bug fixed in HTML lexer to allow use of <?xml in strings in scripts without + triggering xml mode. +
  • +
  • + Bug fixed in SciTE abbreviation expansion that could break indentation or crash. +
  • +
  • + Bug fixed when searching for a whole word string that ends one character before + end of document. +
  • +
  • + Drawing bug fixed when indicators drawn on wrapped lines. +
  • +
  • + Bug fixed when double clicking a hotspot. +
  • +
  • + Bug fixed where autocompletion would remove typed text if no match found. +
  • +
  • + Bug fixed where display does not scroll when inserting in long wrapped line. +
  • +
  • + Bug fixed where SCI_MARKERDELETEALL would only remove one of the markers + on a line that contained multiple markers with the same number. +
  • +
  • + Bug fixed where markers would move when converting line endings. +
  • +
  • + Bug fixed where SCI_LINEENDWRAP would move too far when line ends are visible. +
  • +
  • + Bugs fixed where calltips with unicode or other non-ASCII text would display + incorrectly. +
  • +
  • + Bug fixed in determining if at save point after undoing from save point and then + performing changes. +
  • +
  • + Bug fixed on GTK+ using unsupported code pages where extraneous text could + be drawn. +
  • +
  • + Bug fixed in drag and drop code on Windows where dragging from SciTE to + Firefox could hang both applications. +
  • +
  • + Crashing bug fixed on GTK+ when no font allocation succeeds. +
  • +
  • + Crashing bug fixed when autocompleting word longer than 1000 characters. +
  • +
  • + SciTE crashing bug fixed when both Find and Replace dialogs shown by disallowing + this situation. +
  • +
+

+ Release 1.61 +

+
    +
  • + Released on 29 May 2004. +
  • +
  • + Improvements to selection handling on GTK+. +
  • +
  • + SciTE on GTK+ 2.4 uses the improved file chooser which allows + file extension filters, multiple selection, and remembers favourite + directories. +
  • +
  • + SciTE Load Session and Save Session commands available on GTK+. +
  • +
  • + SciTE lists Lua Startup Script in Options menu when loaded. +
  • +
  • + In SciTE, OnUserListSelection can be implemented in Lua. +
  • +
  • + SciTE on Windows has a context menu on the file tabs. +
  • +
  • + SQL lexer allows '#' comments and optionally '\' quoting inside strings. +
  • +
  • + Mssql lexer improved. +
  • +
  • + AutoIt3 lexer updated. +
  • +
  • + Perl lexer recognizes regular expression use better. +
  • +
  • + Errorlist lexer understands Lua tracebacks and copes with findstr + output for file names that end with digits. +
  • +
  • + Drawing of lines on GTK+ improved and made more like Windows + without final point. +
  • +
  • + SciTE on GTK+ uses a high resolution window icon. +
  • +
  • + SciTE can be set to warn before loading files larger than a particular size. +
  • +
  • + SciTE Lua scripting bugs fixed included a crashing bug when using + an undefined function name that would go before first actual name. +
  • +
  • + SciTE bug fixed where a modified buffer was not saved if it was + the last buffer and was not current when the New command used. +
  • +
  • + SciTE monofont mode no longer affects line numbers. +
  • +
  • + Crashing bug in SciTE avoided by not allowing both the Find and Replace + dialogs to be visible at one time. +
  • +
  • + Crashing bug in SciTE fixed when Lua scripts were being run + concurrently. +
  • +
  • + Bug fixed that caused incorrect line number width in SciTE. +
  • +
  • + PHP folding bug fixed. +
  • +
  • + Regression fixed when setting word characters to not include + some of the standard word characters. +
  • +
+

+ Release 1.60 +

+
    +
  • + Released on 1 May 2004. +
  • +
  • + SciTE can be scripted using the Lua programming language. +
  • +
  • + command.mode is a better way to specify tool command options in SciTE. +
  • +
  • + Continuation markers can be displayed so that you can see which lines are wrapped. +
  • +
  • + Lexer for Gui4Cli language. +
  • +
  • + Lexer for Kix language. +
  • +
  • + Lexer for Specman E language. +
  • +
  • + Lexer for AutoIt3 language. +
  • +
  • + Lexer for APDL language. +
  • +
  • + Lexer for Bash language. Also reasonable for other Unix shells. +
  • +
  • + SciTE can load lexers implemented in external shared libraries. +
  • +
  • + Perl treats "." not as part of an identifier and interprets '/' and '->' + correctly in more circumstances. +
  • +
  • + PHP recognizes variables within strings. +
  • +
  • + NSIS has properties "nsis.uservars" and "nsis.ignorecase". +
  • +
  • + MSSQL lexer adds keyword list for operators and stored procedures, + defines '(', ')', and ',' as operators and changes some other details. +
  • +
  • + Input method preedit window on GTK+ 2 may support some Asian languages. +
  • +
  • + Platform interface adds an extra platform-specific flag to Font::Create. + Used on wxWidgets to choose antialiased text display but may be used for + any task that a platform needs. +
  • +
  • + OnBeforeSave method added to Extension interface. +
  • +
  • + Scintilla methods that return strings can be called with a NULL pointer + to find out how long the string should be. +
  • +
  • + Visual Studio .NET project file now in VS .NET 2003 format so can not be used + directly in VS .NET 2002. +
  • +
  • + Scintilla can be built with GTK+ 2 on Windows. +
  • +
  • + Updated RPM spec for SciTE on GTK+. +
  • +
  • + GTK+ makefile for SciTE allows selection of destination directory, creates destination + directories and sets file modes and owners better. +
  • +
  • + Tab indents now go to next tab multiple rather than add tab size. +
  • +
  • + SciTE abbreviations now use the longest possible match rather than the shortest. +
  • +
  • + Autocompletion does not remove prefix when actioned with no choice selected. +
  • +
  • + Autocompletion cancels when moving beyond the start position, not at the start position. +
  • +
  • + SciTE now shows only calltips for functions that match exactly, not + those that match as a prefix. +
  • +
  • + SciTE can repair box comment sections where some lines were added without + the box comment middle line prefix. +
  • +
  • + Alt+ works in user.shortcuts on Windows. +
  • +
  • + SciTE on GTK+ enables replace in selection for rectangular selections. +
  • +
  • + Key bindings for command.shortcut implemented in a way that doesn't break + when the menus are localized. +
  • +
  • + Drawing of background on GTK+ faster as theme drawing disabled. +
  • +
  • + On GTK+, calltips are moved back onto the screen if they extend beyond the screen bounds. +
  • +
  • + On Windows, the Scintilla object is destroyed on WM_NCDESTROY rather than + WM_DESTROY which arrives earlier. This fixes some problems when Scintilla was subclassed. +
  • +
  • + The zorder switching feature removed due to number of crashing bugs. +
  • +
  • + Code for XPM images made more robust. +
  • +
  • + Bug fixed with primary selection on GTK+. +
  • +
  • + On GTK+ 2, copied or cut text can still be pasted after the Scintilla widget is destroyed. +
  • +
  • + Styling change not visible problem fixed when line was cached. +
  • +
  • + Bug in SciTE on Windows fixed where clipboard commands stopped working. +
  • +
  • + Crashing bugs in display fixed in line layout cache. +
  • +
  • + Crashing bug may be fixed on AMD64 processor on GTK+. +
  • +
  • + Rare hanging crash fixed in Python lexer. +
  • +
  • + Display bugs fixed with DBCS characters on GTK+. +
  • +
  • + Autocompletion lists on GTK+ 2 are not sorted by the ListModel as the + contents are sorted correctly by Scintilla. +
  • +
  • + SciTE fixed to not open extra untitled buffers with check.if.already.open. +
  • +
  • + Sizing bug fixed on GTK+ when window resized while unmapped. +
  • +
  • + Text drawing crashing bug fixed on GTK+ with non-Pango fonts and long strings. +
  • +
  • + Fixed some issues if characters are unsigned. +
  • +
  • + Fixes in NSIS support. +
  • +
+

+ Release 1.59 +

+
    +
  • + Released on 19 February 2004. +
  • +
  • + SciTE Options and Language menus reduced in length by commenting + out some languages. Languages can be enabled by editing the global + properties file. +
  • +
  • + Verilog language supported. +
  • +
  • + Lexer for Microsoft dialect of SQL. SciTE properties file available from extras page. +
  • +
  • + Perl lexer disambiguates '/' better. +
  • +
  • + NSIS lexer improved with a lexical class for numbers, option for ignoring case + of keywords, and folds only occurring when folding keyword first on line. +
  • +
  • + PowerBasic lexer improved with styles for constants and assembler and + folding improvements. +
  • +
  • + On GTK+, input method support only invoked for Asian languages and not + European languages as the old European keyboard code works better. +
  • +
  • + Scintilla can be requested to allocate a certain amount and so avoid repeated + reallocations and memory inefficiencies. SciTE uses this and so should require + less memory. +
  • +
  • + SciTE's "toggle current fold" works when invoked on child line as well as + fold header. +
  • +
  • + SciTE output pane scrolling can be set to not scroll back to start after + completion of command. +
  • +
  • + SciTE has a $(SessionPath) property. +
  • +
  • + SciTE on Windows can use VK_* codes for keys in user.shortcuts. +
  • +
  • + Stack overwrite bug fixed in SciTE's command to move to the end of a + preprocessor conditional. +
  • +
  • + Bug fixed where vertical selection appeared to select a different set of characters + then would be used by, for example, a copy. +
  • +
  • + SciTE memory leak fixed in fold state remembering. +
  • +
  • + Bug fixed where changing the style of some text outside the + standard StyleNeeded notification would not be visible. +
  • +
  • + On GTK+ 2 g_iconv is used in preference to iconv, as it is provided by GTK+ + so should avoid problems finding the iconv library. +
  • +
  • + On GTK+ fixed a style reference count bug. +
  • +
  • + Memory corruption bug fixed with GetSelText. +
  • +
  • + On Windows Scintilla deletes memory on WM_NCDESTROY rather than + the earlier WM_DESTROY to avoid problems when the window is subclassed. +
  • +
+

+ Release 1.58 +

+
    +
  • + Released on 11 January 2004. +
  • +
  • + Method to discover the currently highlighted element in an autocompletion list. +
  • +
  • + On GTK+, the lexers are now included in the scintilla.a library file. This + will require changes to the make files of dependent projects. +
  • +
  • + Octave support added alongside related Matlab language and Matlab support improved. +
  • +
  • + VB lexer gains an unterminated string state and 4 sets of keywords. +
  • +
  • + Ruby lexer handles $' correctly. +
  • +
  • + Error line handling improved for FORTRAN compilers from Absoft and Intel. +
  • +
  • + International input enabled on GTK+ 2 although there is no way to choose an + input method. +
  • +
  • + MultiplexExtension in SciTE allows multiple extensions to be used at once. +
  • +
  • + Regular expression replace interprets backslash expressions \a, \b, \f, \n, \r, \t, + and \v in the replacement value. +
  • +
  • + SciTE Replace dialog displays number of replacements made when Replace All or + Replace in Selection performed. +
  • +
  • + Localization files may contain a translation.encoding setting which is used + on GTK+ 2 to automatically reencode the translation to UTF-8 so it will be + the localized text will be displayed correctly. +
  • +
  • + SciTE on GTK+ implements check.if.already.open. +
  • +
  • + Make files for Mac OS X made more robust. +
  • +
  • + Performance improved in SciTE when switching buffers when there + is a rectangular selection. +
  • +
  • + Fixed failure to display some text when wrapped. +
  • +
  • + SciTE crashes from Ctrl+Tab buffer cycling fixed. + May still be some rare bugs here. +
  • +
  • + Crash fixed when decoding an error message that appears similar to a + Borland error message. +
  • +
  • + Fix to auto-scrolling allows containers to implement enhanced double click selection. +
  • +
  • + Hang fixed in idle word wrap. +
  • +
  • + Crash fixed in hotspot display code.. +
  • +
  • + SciTE on Windows Incremental Search no longer moves caret back. +
  • +
  • + SciTE hang fixed when performing a replace with a find string that + matched zero length strings such as ".*". +
  • +
  • + SciTE no longer styles the whole file when saving buffer fold state + as that was slow. +
  • +
+

+ Release 1.57 +

+
    +
  • + Released on 27 November 2003. +
  • +
  • + SciTE remembers folding of each buffer. +
  • +
  • + Lexer for Erlang language. +
  • +
  • + Scintilla allows setting the set of white space characters. +
  • +
  • + Scintilla has 'stuttered' page movement commands to first move + to top or bottom within current visible lines before scrolling. +
  • +
  • + Scintilla commands for moving to end of words. +
  • +
  • + Incremental line wrap enabled on Windows. +
  • +
  • + SciTE PDF exporter produces output that is more compliant with reader + applications, is smaller and allows more configuration. + HTML exporter optimizes size of output files. +
  • +
  • + SciTE defines properties PLAT_WINNT and PLAT_WIN95 on the + corresponding platforms. +
  • +
  • + SciTE can adjust the line margin width to fit the largest line number. + The line.numbers property is split between line.margin.visible and + line.margin.width. +
  • +
  • + SciTE on GTK+ allows user defined menu accelerators. + Alt can be included in user.shortcuts. +
  • +
  • + SciTE Language menu can have items commented out. +
  • +
  • + SciTE on Windows Go to dialog allows choosing a column number as + well as a line number. +
  • +
  • + SciTE on GTK+ make file uses prefix setting more consistently. +
  • +
  • + Bug fixed that caused word wrapping to fail to display all text. +
  • +
  • + Crashing bug fixed in GTK+ version of Scintilla when using GDK fonts + and opening autocompletion. +
  • +
  • + Bug fixed in Scintilla SCI_GETSELTEXT where an extra NUL + was included at end of returned string +
  • +
  • + Crashing bug fixed in SciTE z-order switching implementation. +
  • +
  • + Hanging bug fixed in Perl lexer. +
  • +
  • + SciTE crashing bug fixed for using 'case' without argument in style definition. +
  • +
+

+ Release 1.56 +

+
    +
  • + Released on 25 October 2003. +
  • +
  • + Rectangular selection can be performed using the keyboard. + Greater programmatic control over rectangular selection. + This has caused several changes to key bindings. +
  • +
  • + SciTE Replace In Selection works on rectangular selections. +
  • +
  • + Improved lexer for TeX, new lexer for Metapost and other support for these + languages. +
  • +
  • + Lexer for PowerBasic. +
  • +
  • + Lexer for Forth. +
  • +
  • + YAML lexer improved to include error styling. +
  • +
  • + Perl lexer improved to correctly handle more cases. +
  • +
  • + Assembler lexer updated to support single-quote strings and fix some + problems. +
  • +
  • + SciTE on Windows can switch between buffers in order of use (z-order) rather + than static order. +
  • +
  • + SciTE supports adding an extension for "Open Selected Filename". + The openpath setting works on GTK+. +
  • +
  • + SciTE can Export as XML. +
  • +
  • + SciTE $(SelHeight) variable gives a more natural result for empty and whole line + selections. +
  • +
  • + Fixes to wrapping problems, such as only first display line being visible in some + cases. +
  • +
  • + Fixes to hotspot to only highlight when over the hotspot, only use background + colour when set and option to limit hotspots to a single line. +
  • +
  • + Small fixes to FORTRAN lexing and folding. +
  • +
  • + SQL lexer treats single quote strings as a separate class to double quote strings.. +
  • +
  • + Scintilla made compatible with expectations of container widget in GTK+ 2.3. +
  • +
  • + Fix to strip out pixmap ID when automatically choosing from an autocompletion + list with only one element. +
  • +
  • + SciTE bug fixed where UTF-8 files longer than 128K were gaining more than one + BOM. +
  • +
  • + Crashing bug fixed in SciTE on GTK+ where using "Stop Executing" twice leads + to all applications exiting. +
  • +
  • + Bug fixed in autocompletion scrolling on GTK+ 2 with a case sensitive list. + The ListBox::Sort method is no longer needed or available so platform + maintainers should remove it. +
  • +
  • + SciTE check.if.already.open setting removed from GTK+ version as unmaintained. +
  • +
+

+ Release 1.55 +

+
    +
  • + Released on 25 September 2003. +
  • +
  • + Fix a crashing bug in indicator display in Scintilla. +
  • +
  • + GTK+ version now defaults to building for GTK+ 2 rather than 1. +
  • +
  • + Mingw make file detects compiler version and avoids options + that are cause problems for some versions. +
  • +
  • + Large performance improvement on GTK+ 2 for long lines. +
  • +
  • + Incremental line wrap on GTK+. +
  • +
  • + International text entry works much better on GTK+ with particular + improvements for Baltic languages and languages that use 'dead' accents. + NUL key events such as those generated by some function keys, ignored. +
  • +
  • + Unicode clipboard support on GTK+. +
  • +
  • + Indicator type INDIC_BOX draws a rectangle around the text. +
  • +
  • + Clarion language support. +
  • +
  • + YAML language support. +
  • +
  • + MPT LOG language support. +
  • +
  • + On Windows, SciTE can switch buffers based on activation order rather + than buffer number. +
  • +
  • + SciTE save.on.deactivate saves all buffers rather than just the current buffer. +
  • +
  • + Lua lexer handles non-ASCII characters correctly. +
  • +
  • + Error lexer understands Borland errors with pathnames that contain space. +
  • +
  • + On GTK+ 2, autocompletion uses TreeView rather than deprecated CList. +
  • +
  • + SciTE autocompletion removed when expand abbreviation command used. +
  • +
  • + SciTE calltips support overloaded functions. +
  • +
  • + When Save fails in SciTE, choice offered to Save As. +
  • +
  • + SciTE message boxes on Windows may be moved to front when needed. +
  • +
  • + Indicators drawn correctly on wrapped lines. +
  • +
  • + Regular expression search no longer matches characters with high bit + set to characters without high bit set. +
  • +
  • + Hang fixed in backwards search in multi byte character documents. +
  • +
  • + Hang fixed in SciTE Mark All command when wrap around turned off. +
  • +
  • + SciTE Incremental Search no longer uses hot keys on Windows. +
  • +
  • + Calltips draw non-ASCII characters correctly rather than as arrows. +
  • +
  • + SciTE crash fixed when going to an error message with empty file name. +
  • +
  • + Bugs fixed in XPM image handling code. +
  • +
+

+ Release 1.54 +

+
    +
  • + Released on 12 August 2003. +
  • +
  • + SciTE on GTK+ 2.x can display a tab bar. +
  • +
  • + SciTE on Windows provides incremental search. +
  • +
  • + Lexer for PostScript. +
  • +
  • + Lexer for the NSIS scripting language. +
  • +
  • + New lexer for POV-Ray Scene Description Language + replaces previous implementation. +
  • +
  • + Lexer for the MMIX Assembler language. +
  • +
  • + Lexer for the Scriptol language. +
  • +
  • + Incompatibility: SQL keywords are specified in lower case rather than upper case. + SQL lexer allows double quoted strings. +
  • +
  • + Pascal lexer: character constants that start with '#' understood, + '@' only allowed within assembler blocks, + '$' can be the start of a number, + initial '.' in 0..constant not treated as part of a number, + and assembler blocks made more distinctive. +
  • +
  • + Lua lexer allows '.' in keywords. + Multi-line strings and comments can be folded. +
  • +
  • + CSS lexer handles multiple psuedoclasses. +
  • +
  • + Properties file folder works for INI file format. +
  • +
  • + Hidden indicator style allows the container to mark text within Scintilla + without there being any visual effect. +
  • +
  • + SciTE does not prompt to save changes when the buffer is empty and untitled. +
  • +
  • + Modification notifications caused by SCI_INSERTSTYLEDSTRING + now include the contents of the insertion. +
  • +
  • + SCI_MARKERDELETEALL deletes all the markers on a line + rather than just the first match. +
  • +
  • + Better handling of 'dead' accents on GTK+ 2 for languages + that use accented characters. +
  • +
  • + SciTE now uses value of output.vertical.size property. +
  • +
  • + Crash fixed in SciTE autocompletion on long lines. +
  • +
  • + Crash fixed in SciTE comment command on long lines. +
  • +
  • + Bug fixed with backwards regular expression search skipping + every second match. +
  • +
  • + Hang fixed with regular expression replace where both target and replacement were empty. +
  • +
+

+ Release 1.53 +

+
    +
  • + Released on 16 May 2003. +
  • +
  • + On GTK+ 2, encodings other than ASCII, Latin1, and Unicode are + supported for both display and input using iconv. +
  • +
  • + External lexers supported on GTK+/Linux. + External lexers must now be explicitly loaded with SCI_LOADLEXERLIBRARY + rather than relying upon a naming convention and automatic loading. +
  • +
  • + Support of Lout typesetting language. +
  • +
  • + Support of E-Scripts language used in the POL Ultima Online Emulator. +
  • +
  • + Scrolling and drawing performance on GTK+ enhanced, particularly for GTK+ 2.x + with an extra window for the text area avoiding conflicts with the scroll bars. +
  • +
  • + CopyText and CopyRange methods in Scintilla allow container to + easily copy to the system clipboard. +
  • +
  • + Line Copy command implemented and bound to Ctrl+Shift+T. +
  • +
  • + Scintilla APIs PositionBefore and PositionAfter can be used to iterate through + a document taking into account the encoding and multi-byte characters. +
  • +
  • + C++ folder can fold on the "} else {" line of an if statement by setting + fold.at.else property to 1. +
  • +
  • + C++ lexer allows an extra set of keywords. +
  • +
  • + Property names and thus abbreviations may be non-ASCII. +
  • +
  • + Removed attempt to load a file when setting properties that was + part of an old scripting experiment. +
  • +
  • + SciTE no longer warns about a file not existing when opening + properties files from the Options menu as there is a good chance + the user wants to create one. +
  • +
  • + Bug fixed with brace recognition in multi-byte encoded files where a partial + character matched a brace byte. +
  • +
  • + More protection against infinite loops or recursion with recursive property definitions. +
  • +
  • + On Windows, cursor will no longer disappear over margins in custom builds when + cursor resource not present. The Windows default cursor is displayed instead. +
  • +
  • + load.on.activate fixed in SciTE as was broken in 1.52. +
  • +
+

+ Release 1.52 +

+
    +
  • + Released on 17 April 2003. +
  • +
  • + Pango font support on GTK+ 2. + Unicode input improved on GTK+ 2. +
  • +
  • + Hotspot style implemented in Scintilla. +
  • +
  • + Small up and down arrows can be displayed in calltips and the container + is notified when the mouse is clicked on a calltip. + Normal and selected calltip text colours can be set. +
  • +
  • + POSIX compatibility flag in Scintilla regular expression search + interprets bare ( and ) as tagged sections. +
  • +
  • + Error message lexer tightened to yield fewer false matches. + Recognition of Lahey and Intel FORTRAN error formats. +
  • +
  • + Scintilla keyboard commands for moving to start and end of + screen lines rather than document lines, unless already there + where these keys move to the start or end of the document line. +
  • +
  • + Line joining command. +
  • +
  • + Lexer for POV-Ray. +
  • +
  • + Calltips on Windows are no longer clipped by the parent window. +
  • +
  • + Autocompletion lists are cancelled when focus leaves their parent window. +
  • +
  • + Move to next/previous empty line delimited paragraph key commands. +
  • +
  • + SciTE hang fixed with recursive property definitions by placing limit + on number of substitutions performed. +
  • +
  • + SciTE Export as PDF reenabled and works. +
  • +
  • + Added loadsession: command line command to SciTE. +
  • +
  • + SciTE option to quit application when last document closed. +
  • +
  • + SciTE option to ask user if it is OK to reload a file that has been + modified outside SciTE. +
  • +
  • + SciTE option to automatically save before running particular command tools + or to ask user or to not save. +
  • +
  • + SciTE on Windows 9x will write a Ctrl+Z to the process input pipe before + closing the pipe when running tool commands that take input. +
  • +
  • + Added a manifest resource to SciTE on Windows to enable Windows XP + themed UI. +
  • +
  • + SciTE calltips handle nested calls and other situations better. +
  • +
  • + CSS lexer improved. +
  • +
  • + Interface to platform layer changed - Surface initialization now requires + a WindowID parameter. +
  • +
  • + Bug fixed with drawing or measuring long pieces of text on Windows 9x + by truncating the pieces. +
  • +
  • + Bug fixed with SciTE on GTK+ where a user shortcut for a visible character + inserted the character as well as executing the command. +
  • +
  • + Bug fixed where primary selection on GTK+ was reset by + Scintilla during creation. +
  • +
  • + Bug fixed where SciTE would close immediately on startup + when using save.session. +
  • +
  • + Crash fixed when entering '\' in LaTeX file. +
  • +
  • + Hang fixed when '#' last character in VB file. +
  • +
  • + Crash fixed in error message lexer. +
  • +
  • + Crash fixed when searching for long regular expressions. +
  • +
  • + Pressing return when nothing selected in user list sends notification with + empty text rather than random text. +
  • +
  • + Mouse debouncing disabled on Windows as it interfered with some + mouse utilities. +
  • +
  • + Bug fixed where overstrike mode inserted before rather than replaced last + character in document. +
  • +
  • + Bug fixed with syntax highlighting of Japanese text. +
  • +
  • + Bug fixed in split lines function. +
  • +
  • + Cosmetic fix to SciTE tab bar on Windows when window resized. + Focus sticks to either pane more consistently. +
  • +
+

+ Release 1.51 +

+
    +
  • + Released on 16 February 2003. +
  • +
  • + Two phase drawing avoids cutting off text that overlaps runs by drawing + all the backgrounds of a line then drawing all the text transparently. + Single phase drawing is an option. +
  • +
  • + Scintilla method to split lines at a particular width by adding new line + characters. +
  • +
  • + The character used in autocompletion lists to separate the text from the image + number can be changed. +
  • +
  • + The scrollbar range will automatically expand when the caret is moved + beyond the current range. + The scroll bar is updated when SCI_SETXOFFSET is called. +
  • +
  • + Mouse cursors on GTK+ improved to be consistent with other applications + and the Windows version. +
  • +
  • + Horizontal scrollbar on GTK+ now disappears in wrapped mode. +
  • +
  • + Scintilla on GTK+ 2: mouse wheel scrolling, cursor over scrollbars, focus, + and syntax highlighting now work. + gtk_selection_notify avoided for compatibility with GTK+ 2.2. +
  • +
  • + Fold margin colours can now be set. +
  • +
  • + SciTE can be built for GTK+ 2. +
  • +
  • + SciTE can optionally preserve the undo history over an automatic file reload. +
  • +
  • + Tags can optionally be case insensitive in XML and HTML. +
  • +
  • + SciTE on Windows handles input to tool commands in a way that should avoid + deadlock. Output from tools can be used to replace the selection. +
  • +
  • + SciTE on GTK+ automatically substitutes '|' for '/' in menu items as '/' + is used to define the menu hierarchy. +
  • +
  • + Optional buffer number in SciTE title bar. +
  • +
  • + Crash fixed in SciTE brace matching. +
  • +
  • + Bug fixed where automatic scrolling past end of document + flipped back to the beginning. +
  • +
  • + Bug fixed where wrapping caused text to disappear. +
  • +
  • + Bug fixed on Windows where images in autocompletion lists were + shown on the wrong item. +
  • +
  • + Crash fixed due to memory bug in autocompletion lists on Windows. +
  • +
  • + Crash fixed when double clicking some error messages. +
  • +
  • + Bug fixed in word part movement where sometimes no movement would occur. +
  • +
  • + Bug fixed on Windows NT where long text runs were truncated by + treating NT differently to 9x where there is a limitation. +
  • +
  • + Text in not-changeable style works better but there remain some cases where + it is still possible to delete text protected this way. +
  • +
+

+ Release 1.50 +

+
    +
  • + Released on 24 January 2003. +
  • +
  • + Autocompletion lists may have a per-item pixmap. +
  • +
  • + Autocompletion lists allow Unicode text on Windows. +
  • +
  • + Scintilla documentation rewritten. +
  • +
  • + Additional DBCS encoding support in Scintilla on GTK+ primarily aimed at + Japanese EUC encoding. +
  • +
  • + CSS (Cascading Style Sheets) lexer added. +
  • +
  • + diff lexer understands some more formats. +
  • +
  • + Fold box feature is an alternative way to show the structure of code. +
  • +
  • + Avenue lexer supports multiple keyword lists. +
  • +
  • + The caret may now be made invisible by setting the caret width to 0. +
  • +
  • + Python folder attaches comments before blocks to the next block rather + than the previous block. +
  • +
  • + SciTE openpath property on Windows searches a path for files that are + the subject of the Open Selected Filename command. +
  • +
  • + The localization file name can be changed with the locale.properties property. +
  • +
  • + On Windows, SciTE can pipe the result of a string expression into a command line tool. +
  • +
  • + On Windows, SciTE's Find dialog has a Mark All button. +
  • +
  • + On Windows, there is an Insert Abbreviation command that allows a choice from + the defined abbreviations and inserts the selection into the abbreviation at the + position of a '|'. +
  • +
  • + Minor fixes to Fortran lexer. +
  • +
  • + fold.html.preprocessor decides whether to fold <? and ?>. + Minor improvements to PHP folding. +
  • +
  • + Maximum number of keyword lists allowed increased from 6 to 9. +
  • +
  • + Duplicate line command added with default assignment to Ctrl+D. +
  • +
  • + SciTE sets $(Replacements) to the number of replacements made by the + Replace All command. $(CurrentWord) is set to the word before the caret if the caret + is at the end of a word. +
  • +
  • + Opening a SciTE session now loads files in remembered order, sets the current file + as remembered, and moves the caret to the remembered line. +
  • +
  • + Bugs fixed with printing on Windows where line wrapping was causing some text + to not print. +
  • +
  • + Bug fixed with Korean Input Method Editor on Windows. +
  • +
  • + Bugs fixed with line wrap which would sometimes choose different break positions + after switching focus away and back. +
  • +
  • + Bug fixed where wheel scrolling had no effect on GTK+ after opening a fold. +
  • +
  • + Bug fixed with file paths containing non-ASCII characters on Windows. +
  • +
  • + Crash fixed with printing on Windows after defining pixmap marker. +
  • +
  • + Crash fixed in makefile lexer when first character on line was '='. +
  • +
  • + Bug fixed where local properties were not always being applied. +
  • +
  • + Ctrl+Keypad* fold command works on GTK+. +
  • +
  • + Hangs fixed in SciTE's Replace All command when replacing regular expressions '^' + or '$'. +
  • +
  • + SciTE monospace setting behaves more sensibly. +
  • +
+

+ Release 1.49 +

+
    +
  • + Released on 1 November 2002. +
  • +
  • + Unicode supported on GTK+. To perform well, this added a font cache to GTK+ + and to make that safe, a mutex is used. The mutex requires the application to link in + the threading library by evaluating `glib-config --libs gthread`. A Unicode locale + should also be set up by a call like setlocale(LC_CTYPE, "en_US.UTF-8"). + scintilla_release_resources function added to release mutex. +
  • +
  • + FORTRAN and assembler lexers added along with other support for these + languages in SciTE. +
  • +
  • + Ada lexer improved handling of based numbers, identifier validity and attributes + distinguished from character literals. +
  • +
  • + Lua lexer handles block comments and a deep level of nesting for literal strings + and block comments. +
  • +
  • + Errorlist lexer recognizes PHP error messages. +
  • +
  • + Variant of the C++ lexer with case insensitive keywords + called cppnocase. Whitespace in preprocessor text handled more correctly. +
  • +
  • + Folder added for Perl. +
  • +
  • + Compilation with GCC 3.2 supported. +
  • +
  • + Markers can be pixmaps. +
  • +
  • + Lines are wrapped when printing. + Bug fixed which printed line numbers in different styles. +
  • +
  • + Text can be appended to end with AppendText method. +
  • +
  • + ChooseCaretX method added. +
  • +
  • + Vertical scroll bar can be turned off with SetVScrollBar method. +
  • +
  • + SciTE Save All command saves all buffers. +
  • +
  • + SciTE localization compares keys case insensitively to make translations more flexible. +
  • +
  • + SciTE detects a utf-8 coding cookie "coding: utf-8" in first two + lines and goes into Unicode mode. +
  • +
  • + SciTE key bindings are definable. +
  • +
  • + SciTE Find in Files dialog can display directory browser to + choose directory to search. +
  • +
  • + SciTE enabling of undo and redo toolbar buttons improved. +
  • +
  • + SciTE on Windows file type filters in open dialog sorted. +
  • +
  • + Fixed crashing bug when using automatic tag closing in XML or HTML. +
  • +
  • + Fixed bug on Windows causing very long (>64K) lines to not display. +
  • +
  • + Fixed bug in backwards regular expression searching. +
  • +
  • + Fixed bug in calltips where wrong argument was highlighted. +
  • +
  • + Fixed bug in tab timmy feature when file has line feed line endings. +
  • +
  • + Fixed bug in compiling without INCLUDE_DEPRECATED_FEATURES + defined. +
  • +
+

+ Release 1.48 +

+
    +
  • + Released on 9 September 2002. +
  • +
  • + Improved Pascal lexer with context sensitive keywords + and separate folder which handles //{ and //} folding comments and + {$region} and {$end} folding directives. + The "case" statement now folds correctly. +
  • +
  • + C++ lexer correctly handles comments on preprocessor lines. +
  • +
  • + New commands for moving to beginning and end of display lines when in line + wrap mode. Key bindings added for these commands. +
  • +
  • + New marker symbols that look like ">>>" and "..." which can be used for + interactive shell prompts for Python. +
  • +
  • + The foreground and background colours of visible whitespace can be chosen + independent of the colours chosen for the lexical class of that whitespace. +
  • +
  • + Per line data optimized by using an exponential allocation scheme. +
  • +
  • + SciTE API file loading optimized. +
  • +
  • + SciTE for GTK+ subsystem 2 documented. The exit status of commands + is decoded into more understandable fields. +
  • +
  • + SciTE find dialog remembers previous find string when there is no selection. + Find in Selection button disabled when selection is rectangular as command + did not work. +
  • +
  • + Shift+Enter made equivalent to Enter to avoid users having to let go of + the shift key when typing. Avoids the possibility of entering single carriage + returns in a file that contains CR+LF line ends. +
  • +
  • + Autocompletion does not immediately disappear when the length parameter + to SCI_AUTOCSHOW is 0. +
  • +
  • + SciTE focuses on the editor pane when File | New executed and when the + output pane is closed with F8. Double clicking on a non-highlighted output + pane line selects the word under the cursor rather than seeking the next + highlighted line. +
  • +
  • + SciTE director interface implements an "askproperty" command. +
  • +
  • + SciTE's Export as LaTeX output improved. +
  • +
  • + Better choice of autocompletion displaying above the caret rather than + below when that is more sensible. +
  • +
  • + Bug fixed where context menu would not be completely visible if invoked + when cursor near bottom or left of screen. +
  • +
  • + Crashing bug fixed when displaying long strings on GTK+ caused failure of X server + by displaying long text in segments. +
  • +
  • + Crashing bug fixed on GTK+ when a Scintilla window was removed from its parent + but was still the selection owner. +
  • +
  • + Bug fixed on Windows in Unicode mode where not all characters on a line + were displayed when that line contained some characters not in ASCII. +
  • +
  • + Crashing bug fixed in SciTE on Windows with clearing output while running command. +
  • +
  • + Bug fixed in SciTE for GTK+ with command completion not detected when + no output was produced by the command. +
  • +
  • + Bug fixed in SciTE for Windows where menus were not shown translated. +
  • +
  • + Bug fixed where words failed to display in line wrapping mode with visible + line ends. +
  • +
  • + Bug fixed in SciTE where files opened from a session file were not closed. +
  • +
  • + Cosmetic flicker fixed when using Ctrl+Up and Ctrl+Down with some caret policies. +
  • +
+

+ Release 1.47 +

+
    +
  • + Released on 1 August 2002. +
  • +
  • + Support for GTK+ 2 in Scintilla. International input methods not supported + on GTK+2. +
  • +
  • + Line wrapping performance improved greatly. +
  • +
  • + New caret policy implementation that treats horizontal and vertical + positioning equivalently and independently. Old caret policy methods + deprecated and not all options work correctly with old methods. +
  • +
  • + Extra fold points for C, C++, Java, ... for fold comments //{ .. //} and + #if / #ifdef .. #endif and the #region .. #endregion feature of C#. +
  • +
  • + Scintilla method to find the height in pixels of a line. Currently returns the + same result for every line as all lines are same height. +
  • +
  • + Separate make file, scintilla_vc6.mak, for Scintilla to use Visual C++ + version 6 since main makefile now assumes VS .NET. + VS .NET project files available for combined Scintilla and + SciTE in scite/boundscheck. +
  • +
  • + SciTE automatically recognizes Unicode files based + on their Byte Order Marks and switches to Unicode mode. + On Windows, where SciTE supports Unicode display, this + allows display of non European characters. + The file is saved back into the same character encoding unless + the user decides to switch using the File | Encoding menu. +
  • +
  • + Handling of character input changed so that a fillup character, typically '(' + displays a calltip when an autocompletion list was being displayed. +
  • +
  • + Multiline strings lexed better for C++ and Lua. +
  • +
  • + Regular expressions in JavaScript within hypertext files are lexed better. +
  • +
  • + On Windows, Scintilla exports a function called Scintilla_DirectFunction + that can be used the same as the function returned by GetDirectFunction. +
  • +
  • + Scintilla converts line endings of text obtained from the clipboard to + the current default line endings. +
  • +
  • + New SciTE property ensure.final.line.end can ensure that saved files + always end with a new line as this is required by some tools. + The ensure.consistent.line.ends property ensures all line ends are the + current default when saving files. + The strip.trailing.spaces property now works on the buffer so the + buffer in memory and the file on disk are the same after a save is performed. +
  • +
  • + The SciTE expand abbreviation command again allows '|' characters + in expansions to be quoted by using '||'. +
  • +
  • + SciTE on Windows can send data to the find tool through standard + input rather than using a command line argument to avoid problems + with quoting command line arguments. +
  • +
  • + The Stop Executing command in SciTE on Windows improved to send + a Ctrl+Z character to the tool. Better messages when stopping a tool. +
  • +
  • + Autocompletion can automatically "fill up" when one of a set of characters is + type with the autocomplete.<lexer>.fillups property. +
  • +
  • + New predefined properties in SciTE, SelectionStartColumn, SelectionStartLine, + SelectionEndColumn, SelectionEndLine can be used to integrate with other + applications. +
  • +
  • + Environment variables are available as properties in SciTE. +
  • +
  • + SciTE on Windows keeps status line more current. +
  • +
  • + Abbreviations work in SciTE on Linux when first opened. +
  • +
  • + File saving fixed in SciTE to ensure files are not closed when they can not be + saved because of file permissions. Also fixed a problem with buffers that + caused files to not be saved. +
  • +
  • + SciTE bug fixed where monospace mode not remembered when saving files. + Some searching options now remembered when switching files. +
  • +
  • + SciTE on Linux now waits on child termination when it shuts a child down + to avoid zombies. +
  • +
  • + SciTE on Linux has a Print menu command that defaults to invoking a2ps. +
  • +
  • + Fixed incorrect highlighting of indentation guides in SciTE for Python. +
  • +
  • + Crash fixed in Scintilla when calling GetText for 0 characters. +
  • +
  • + Exporting as LaTeX improved when processing backslashes and tabs + and setting up font. +
  • +
  • + Crash fixed in SciTE when exporting or copying as RTF. +
  • +
  • + SciTE session loading fixed to handle more than 10 files in session. +
  • +
+

+ Release 1.46 +

+
    +
  • + Released on 10 May 2002. +
  • +
  • + Set of lexers compiled into Scintilla can now be changed by adding and + removing lexer source files from scintilla/src and running LexGen.py. +
  • +
  • + SCN_ZOOM notification provided by Scintilla when user changes zoom level. + Method to determine width of strings in pixels so that elements can be sized + relative to text size. + SciTE changed to keep line number column displaying a given + number of characters. +
  • +
  • + The logical width of the document used to determine scroll bar range can be set. +
  • +
  • + Setting to allow vertical scrolling to display last line at top rather than + bottom of window. +
  • +
  • + Read-only mode improved to avoid changing the selection in most cases + when a modification is attempted. Drag and drop cursors display correctly + for read-only in some cases. +
  • +
  • + Visual C++ options in make files changed to suit Visual Studio .NET. +
  • +
  • + Scintilla.iface includes feature types for enumerations and lexers. +
  • +
  • + Lua lexer improves handling of literal strings and copes with nested literal strings. +
  • +
  • + Diff lexer changed to treat lines starting with "***" similarly to "---". + Symbolic names defined for lexical classes. +
  • +
  • + nncrontab lexer improved. +
  • +
  • + Turkish fonts (iso8859-9) supported on GTK+. +
  • +
  • + Automatic close tag feature for XML and HTML in SciTE. +
  • +
  • + Automatic indentation in SciTE improved. +
  • +
  • + Maximum number of buffers available in SciTE increased. May be up to 100 + although other restrictions on menu length limit the real maximum. +
  • +
  • + Save a Copy command added to SciTE. +
  • +
  • + Export as TeX command added to SciTE. +
  • +
  • + Export as HTML command in SciTE respects Use Monospaced Font and + background colour settings. +
  • +
  • + Compilation problem on Solaris fixed. +
  • +
  • + Order of files displayed for SciTE's previous and next menu and key commands + are now consistent. +
  • +
  • + Saving of MRU in recent file changed so files open when SciTE quit + are remembered. +
  • +
  • + More variants of ctags tags handled by Open Selected Filename in SciTE. +
  • +
  • + JavaScript embedded in XML highlighted again. +
  • +
  • + SciTE status bar updated after changing parameters in case they are being + displayed in status bar. +
  • +
  • + Crash fixed when handling some multi-byte languages. +
  • +
  • + Crash fixed when replacing end of line characters. +
  • +
  • + Bug in SciTE fixed in multiple buffer mode where automatic loading + turned on could lead to losing file contents. +
  • +
  • + Bug in SciTE on GTK+ fixed where dismissing dialogs with close box led to + those dialogs never being shown again. +
  • +
  • + Bug in SciTE on Windows fixed where position.tile with default positions + led to SciTE being positioned off-screen. +
  • +
  • + Bug fixed in read-only mode, clearing all deletes contraction state data + leading to it not being synchronized with text. +
  • +
  • + Crash fixed in SciTE on Windows when tab bar displayed. +
  • +
+

+ Release 1.45 +

+
    +
  • + Released on 15 March 2002. +
  • +
  • + Line layout cache implemented to improve performance by maintaining + the positioning of characters on lines. Can be set to cache nothing, + the line with the caret, the visible page or the whole document. +
  • +
  • + Support, including a new lexer, added for Matlab programs. +
  • +
  • + Lua folder supports folding {} ranges and compact mode. + Lua lexer styles floating point numbers in number style instead of + setting the '.' in operator style. + Up to 6 sets of keywords. + Better support for [[ although only works well + when all on one line. +
  • +
  • + Python lexer improved to handle floating point numbers that contain negative + exponents and that start with '.'. +
  • +
  • + When performing a rectangular paste, the caret now remains at the + insertion point. +
  • +
  • + On Windows with a wheel mouse, page-at-a-time mode is recognized. +
  • +
  • + Read-only mode added to SciTE with a property to initialize it and another property, + $(ReadOnly) available to show this mode in the status bar. +
  • +
  • + SciTE status bar can show the number of lines in the selection + with the $(SelHeight) property. +
  • +
  • + SciTE's "Export as HTML" command uses the current character set to produce + correct output for non-Western-European character sets, such as Russian. +
  • +
  • + SciTE's "Export as RTF" fixed to produce correct output when file contains '\'. +
  • +
  • + SciTE goto command accepts a column as well as a line. + If given a column, it selects the word at that column. +
  • +
  • + SciTE's Build, Compile and Go commands are now disabled if no + action has been assigned to them. +
  • +
  • + The Refresh button in the status bar has been removed from SciTE on Windows. +
  • +
  • + Bug fixed in line wrap mode where cursor up or down command did not work. +
  • +
  • + Some styling bugs fixed that were due to a compilation problem with + gcc and inline functions with same name but different code. +
  • +
  • + The way that lexers loop over text was changed to avoid accessing beyond the + end or setting beyond the end. May fix some bugs and make the code safer but + may also cause new bugs. +
  • +
  • + Bug fixed in HTML lexer's handling of SGML. +
  • +
  • + Bug fixed on GTK+/X where lines wider than 32767 pixels did not display. +
  • +
  • + SciTE bug fixed with file name generation for standard property files. +
  • +
  • + SciTE bug fixed with Open Selected Filename command when used with + file name and line number combination. +
  • +
  • + In SciTE, indentation and tab settings stored with buffers so maintained correctly + as buffers selected. + The properties used to initialize these settings can now be set separately for different + file patterns. +
  • +
  • + Thread safety improved on Windows with a critical section protecting the font + cache and initialization of globals performed within Scintilla_RegisterClasses. + New Scintilla_ReleaseResources call provided to allow explicit freeing of resources + when statically bound into another application. Resources automatically freed + in DLL version. The window classes are now unregistered as part of resource + freeing which fixes bugs that occurred in some containers such as Internet Explorer. +
  • +
  • + 'make install' fixed on Solaris. +
  • +
  • + Bug fixed that could lead to a file being opened twice in SciTE. +
  • +
+

+ Release 1.44 +

+
    +
  • + Released on 4 February 2002. +
  • +
  • + Crashing bug fixed in Editor::Paint. +
  • +
  • + Lua lexer no longer treats '.' as a word character and + handles 6 keyword sets. +
  • +
  • + WordStartPosition and WordEndPosition take an onlyWordCharacters + argument. +
  • +
  • + SciTE option for simplified automatic indentation which repeats + the indentation of the previous line. +
  • +
  • + Compilation fix on Alpha because of 64 bit. +
  • +
  • + Compilation fix for static linking. +
  • +
  • + Limited maximum line length handled to 8000 characters as previous + value of 16000 was causing stack exhaustion crashes for some. +
  • +
  • + When whole document line selected, only the last display line gets + the extra selected rectangle at the right hand side rather than + every display line. +
  • +
  • + Caret disappearing bug fixed for the case that the caret was not on the + first display line of a document line. +
  • +
  • + SciTE bug fixed where untitled buffer containing text was sometimes + deleted without chance to save. +
  • +
  • + SciTE bug fixed where use.monospaced not working with + multiple buffers. +
  • +
+

+ Release 1.43 +

+
    +
  • + Released on 19 January 2002. +
  • +
  • + Line wrapping robustness and performance improved in Scintilla. +
  • +
  • + Line wrapping option added to SciTE for both edit and output panes. +
  • +
  • + Static linking on Windows handles cursor resource better. + Documentation of static linking improved. +
  • +
  • + Autocompletion has an option to delete any word characters after the caret + upon selecting an item. +
  • +
  • + FOX version identified by PLAT_FOX in Platform.h. +
  • +
  • + Calltips in SciTE use the calltip.<lexer>.word.characters setting to + correctly find calltips for functions that include characters like '$' which + is not normally considered a word character. +
  • +
  • + SciTE has a command to show help on itself which gets hooked up to displaying + SciTEDoc.html. +
  • +
  • + SciTE option calltip.<lexer>.end.definition to display help text on a + second line of calltip. +
  • +
  • + Fixed the handling of the Buffers menu on GTK+ to ensure current buffer + indicated and no warnings occur. + Changed some menu items on GTK+ version to be same as Windows version. +
  • +
  • + use.monospaced property for SciTE determines initial state of Use Monospaced Font + setting. +
  • +
  • + The SciTE Complete Symbol command now works when there are no word + characters before the caret, even though it is slow to display the whole set of + symbols. +
  • +
  • + Function names removed from SciTE's list of PHP keywords. The full list of + predefined functions is available from another web site mentioned on the + Extras page. +
  • +
  • + Crashing bug at startup on GTK+ for some configurations fixed. +
  • +
  • + Crashing bug on GTK+ on 64 bit platforms fixed. +
  • +
  • + Compilation problem with some compilers fixed in GTK+. +
  • +
  • + Japanese text entry improved on Windows 9x. +
  • +
  • + SciTE recent files directory problem on Windows when HOME and SciTE_HOME + environment variables not set is now the directory of the executable. +
  • +
  • + Session files no longer include untitled buffers. +
  • +
+

+ Release 1.42 +

+
    +
  • + Released on 24 December 2001. +
  • +
  • + Better localization support including context menus and most messages. + Translations of the SciTE user interface available for Bulgarian, + French, German, Italian, Russian, and Turkish. +
  • +
  • + Can specify a character to use to indicate control characters + rather than having them displayed as mnemonics. +
  • +
  • + Scintilla key command for backspace that will not delete line + end characters. +
  • +
  • + Scintilla method to find start and end of words. +
  • +
  • + SciTE on GTK+ now supports the load.on.activate and save.on.deactivate + properties in an equivalent way to the Windows version. +
  • +
  • + The output pane of SciTE on Windows is now interactive so command line + utilities that prompt for input or confirmation can be used. +
  • +
  • + SciTE on Windows can choose directory for a "Find in Files" + command like the GTK+ version could. +
  • +
  • + SciTE can now load a set of API files rather than just one file. +
  • +
  • + ElapsedTime class added to Platform for accurate measurement of durations. + Used for debugging and for showing the user how long commands take in SciTE. +
  • +
  • + Baan lexer added. +
  • +
  • + In C++ lexer, document comment keywords no longer have to be at the start + of the line. +
  • +
  • + PHP lexer changed to match keywords case insensitively. +
  • +
  • + More shell keywords added. +
  • +
  • + SciTE support for VoiceXML added to xml.properties. +
  • +
  • + In SciTE the selection is not copied to the find field of the Search and Replace + dialogs if it contains end of line characters. +
  • +
  • + SciTE on Windows has a menu item to decide whether to respond to other + instances which are performing their check.if.already.open check. +
  • +
  • + SciTE accelerator key for Box Comment command changed to avoid problems + in non-English locales. +
  • +
  • + SciTE context menu includes Close command for the editor pane and + Hide command for the output pane. +
  • +
  • + output: command added to SciTE director interface to add text to the + output pane. The director interface can execute commands (such as tool + commands with subsystem set to 3) by sending a macro:run message. +
  • +
  • + SciTE on GTK+ will defer to the Window Manager for position if position.left or + position.top not set and for size if position.width or position.height not set. +
  • +
  • + SciTE on Windows has a position.tile property to place a second instance + to the right of the first. +
  • +
  • + Scintilla on Windows again supports EM_GETSEL and EM_SETSEL. +
  • +
  • + Problem fixed in Scintilla on Windows where control ID is no longer cached + as it could be changed by external code. +
  • +
  • + Problems fixed in SciTE on Windows when finding any other open instances at + start up when check.if.already.open is true. +
  • +
  • + Bugs fixed in SciTE where command strings were not always having + variables evaluated. +
  • +
  • + Bugs fixed with displaying partial double-byte and Unicode characters + in rectangular selections and at the edge when edge mode is EDGE_BACKGROUND. + Column numbers reported by GetColumn treat multiple byte characters as one column + rather than counting bytes. +
  • +
  • + Bug fixed with caret movement over folded lines. +
  • +
  • + Another bug fixed with tracking selection in secondary views when performing + modifications. +
  • +
  • + Horizontal scrolling and display of long lines optimized. +
  • +
  • + Cursor setting in Scintilla on GTK+ optimized. +
  • +
  • + Experimental changeable style attribute. + Set to false to make text read-only. + Currently only stops caret from being within not-changeable + text and does not yet stop deleting a range that contains + not-changeable text. + Can be used from SciTE by adding notchangeable to style entries. +
  • +
  • + Experimental line wrapping. + Currently has performance and appearance problems. +
  • +
+

+ Release 1.41 +

+
    +
  • + Released on 6 November 2001. +
  • +
  • + Changed Platform.h to not include platform headers. This lessens likelihood and impact of + name clashes from system headers and also speeds up compilation. + Renamed DrawText to DrawTextNoClip to avoid name clash. +
  • +
  • + Changed way word functions work to treat a sequence of punctuation as + a word. This is more sensible and also more compatible with other editors. +
  • +
  • + Cursor changes over the margins and selection on GTK+ platform. +
  • +
  • + SC_MARK_BACKGROUND is a marker that only changes the line's background colour. +
  • +
  • + Enhanced Visual Basic lexer handles character date and octal literals, + and bracketed keywords for VB.NET. There are two VB lexers, vb and vbscript + with type indication characters like ! and $ allowed at the end of identifiers + in vb but not vbscript. Lexer states now separate from those used for C++ and + names start with SCE_B. +
  • +
  • + Lexer added for Bullant language. +
  • +
  • + The horizontal scroll position, xOffset, is now exposed through the API. +
  • +
  • + The SCN_POSCHANGED notification is deprecated as it was causing confusion. + Use SCN_UPDATEUI instead. +
  • +
  • + Compilation problems fixed for some versions of gcc. +
  • +
  • + Support for WM_GETTEXT restored on Windows. +
  • +
  • + Double clicking on an autocompletion list entry works on GTK+. +
  • +
  • + Bug fixed with case insensitive sorts for autocompletion lists. +
  • +
  • + Bug fixed with tracking selection in secondary views when performing modifications. +
  • +
  • + SciTE's abbreviation expansion feature will now indent expansions to the current + indentation level if indent.automatic is on. +
  • +
  • + SciTE allows setting up of parameters to commands from a dialog and can also + show this dialog automatically to prompt for arguments when running a command. +
  • +
  • + SciTE's Language menu (formerly Options | Use Lexer) is now defined by the + menu.language property rather than being hardcoded. +
  • +
  • + The user interface of SciTE can be localized to a particular language by editing + a locale.properties file. +
  • +
  • + On Windows, SciTE will try to move to the front when opening a new file from + the shell and using check.if.already.open. +
  • +
  • + SciTE can display the file name and directory in the title bar in the form + "file @ directory" when title.full.path=2. +
  • +
  • + The SciTE time.commands property reports the time taken by a command as well + as its status when completed. +
  • +
  • + The SciTE find.files property is now a list separated by '|' characters and this list is + added into the Files pull down of the Find in Files dialog. +
  • +
+

+ Release 1.40 +

+
    +
  • + Released on 23 September 2001. +
  • +
  • + Removal of emulation of Win32 RichEdit control in core of Scintilla. + This change may be incompatible with existing client code. + Some emulation still done in Windows platform layer. +
  • +
  • + SGML support in the HTML/XML lexer. +
  • +
  • + SciTE's "Stop Executing" command will terminate GUI programs on + Windows NT and Windows 2000. +
  • +
  • + StyleContext class helps construct lexers that are simple and accurate. + Used in the C++, Eiffel, and Python lexers. +
  • +
  • + Clipboard operations in GTK+ version convert between platform '\n' line endings and + currently chosen line endings. +
  • +
  • + Any character in range 0..255 can be used as a marker. + This can be used to support numbered bookmarks, for example. +
  • +
  • + The default scripting language for ASP can be set. +
  • +
  • + New lexer and other support for crontab files used with the nncron scheduler. +
  • +
  • + Folding of Python improved. +
  • +
  • + The ` character is treated as a Python operator. +
  • +
  • + Line continuations ("\" at end of line) handled inside Python strings. +
  • +
  • + More consistent handling of line continuation ('\' at end of line) in + C++ lexer. + This fixes macro definitions that span more than one line. +
  • +
  • + C++ lexer can understand Doxygen keywords in doc comments. +
  • +
  • + SciTE on Windows allows choosing to open the "open" dialog on the directory + of the current file rather than in the default directory. +
  • +
  • + SciTE on Windows handles command line arguments in "check.if.already.open" + correctly when the current directory of the new instance is different to the + already open instance of SciTE. +
  • +
  • + "cwd" command (change working directory) defined for SciTE director interface. +
  • +
  • + SciTE "Export As HTML" produces better, more compliant, and shorter files. +
  • +
  • + SciTE on Windows allows several options for determining default file name + for exported files. +
  • +
  • + Automatic indentation of Python in SciTE fixed. +
  • +
  • + Exported HTML can support folding. +
  • +
  • + Bug fixed in SCI_GETTEXT macro command of director interface. +
  • +
  • + Cursor leak fixed on GTK+. +
  • +
  • + During SciTE shutdown, "identity" messages are no longer sent over the director interface. +
  • +
+

+ Release 1.39 +

+
    +
  • + Released on 22 August 2001. +
  • +
  • + Windows version requires msvcrt.dll to be available so will not work + on original Windows 95 version 1. The msvcrt.dll file is installed + by almost everything including Internet Explorer so should be available. +
  • +
  • + Flattened tree control style folding margin. The SciTE fold.plus option is + now fold.symbols and has more values for the new styles. +
  • +
  • + Mouse dwell events are generated when the user holds the mouse steady + over Scintilla. +
  • +
  • + PositionFromPointClose is like PositionFromPoint but returns + INVALID_POSITION when point outside window or after end of line. +
  • +
  • + Input of Hungarian and Russian characters in GTK+ version works by + truncating input to 8 bits if in the range of normal characters. +
  • +
  • + Better choices for font descriptors on GTK+ for most character sets. +
  • +
  • + GTK+ Scintilla is destroyed upon receiving destroy signal rather than + destroy_event signal. +
  • +
  • + Style setting that force upper or lower case text. +
  • +
  • + Case-insensitive autocompletion lists work correctly. +
  • +
  • + Keywords can be prefix based so ^GTK_ will treat all words that start + with GTK_ as keywords. +
  • +
  • + Horizontal scrolling can be jumpy rather than gradual. +
  • +
  • + GetSelText places a '\0' in the buffer if the selection is empty.. +
  • +
  • + EnsureVisible split into two methods EnsureVisible which will not scroll to show + the line and EnsureVisibleEnforcePolicy which may scroll. +
  • +
  • + Python folder has options to fold multi-line comments and triple quoted strings. +
  • +
  • + C++ lexer handles keywords before '.' like "this.x" in Java as keywords. + Compact folding mode option chooses whether blank lines after a structure are + folded with that structure. Second set of keywords with separate style supported. +
  • +
  • + Ruby lexer handles multi-line comments. +
  • +
  • + VB has folder. +
  • +
  • + PHP lexer has an operator style, handles "<?" and "?>" inside strings + and some comments. +
  • +
  • + TCL lexer which is just an alias for the C++ lexer so does not really + understand TCL syntax. +
  • +
  • + Error lines lexer has styles for Lua error messages and .NET stack traces. +
  • +
  • + Makefile lexer has a target style. +
  • +
  • + Lua lexer handles some [[]] string literals. +
  • +
  • + HTML and XML lexer have a SCE_H_SGML state for tags that + start with "<!". +
  • +
  • + Fixed Scintilla bugs with folding. When modifications were performed near + folded regions sometimes no unfolding occurred when it should have. Deleting a + fold causing character sometimes failed to update fold information correctly. +
  • +
  • + Better support for Scintilla on GTK+ for Win32 including separate + PLAT_GTK_WIN32 definition and correct handling of rectangular selection + with clipboard operations. +
  • +
  • + SciTE has a Tools | Switch Pane (Ctrl+F6) command to switch focus between + edit and output panes. +
  • +
  • + SciTE option output.scroll allows automatic scrolling of output pane to + be turned off. +
  • +
  • + Commands can be typed into the SciTE output pane similar to a shell window. +
  • +
  • + SciTE properties magnification and output magnification set initial zoom levels. +
  • +
  • + Option for SciTE comment block command to place comments at start of line. +
  • +
  • + SciTE for Win32 has an option to minimize to the tray rather than the task bar. +
  • +
  • + Close button on SciTE tool bar for Win32. +
  • +
  • + SciTE compiles with GCC 3.0. +
  • +
  • + SciTE's automatic indentation of C++ handles braces without preceding keyword + correctly. +
  • +
  • + Bug fixed with GetLine method writing past the end of where it should. +
  • +
  • + Bug fixed with mouse drag automatic scrolling when some lines were folded. +
  • +
  • + Bug fixed because caret XEven setting was inverted. +
  • +
  • + Bug fixed where caret was initially visible even though window was not focussed. +
  • +
  • + Bug fixed where some file names could end with "\\" which caused slow + downs on Windows 9x. +
  • +
  • + On Win32, SciTE Replace dialog starts with focus on replacement text. +
  • +
  • + SciTE Go to dialog displays correct current line. +
  • +
  • + Fixed bug with SciTE opening multiple files at once. +
  • +
  • + Fixed bug with Unicode key values reported to container truncated. +
  • +
  • + Fixed bug with unnecessary save point notifications. +
  • +
  • + Fixed bugs with indenting and unindenting at start of line. +
  • +
  • + Monospace Font setting behaves more consistently. +
  • +
+

+ Release 1.38 +

+
    +
  • + Released on 23 May 2001. +
  • +
  • + Loadable lexer plugins on Windows. +
  • +
  • + Ruby lexer and support. +
  • +
  • + Lisp lexer and support. +
  • +
  • + Eiffel lexer and support. +
  • +
  • + Modes for better handling of Tab and BackSpace keys within + indentation. Mode to avoid autocompletion list cancelling when + there are no viable matches. +
  • +
  • + ReplaceTarget replaced with two calls ReplaceTarget + (which is incompatible with previous ReplaceTarget) and + ReplaceTargetRE. Both of these calls have a count first + parameter which allows using strings containing nulls. + SearchInTarget and SetSearchFlags functions allow + specifying a search in several simple steps which helps + some clients which can not create structs or pointers easily. +
  • +
  • + Asian language input through an Input Method Editor works + on Windows 2000. +
  • +
  • + On Windows, control characters can be entered through use of + the numeric keypad in conjunction with the Alt key. +
  • +
  • + Document memory allocation changed to grow exponentially + which reduced time to load a 30 Megabyte file from + 1000 seconds to 25. Change means more memory may be used. +
  • +
  • + Word part movement keys now handled in Scintilla rather than + SciTE. +
  • +
  • + Regular expression '^' and '$' work more often allowing insertion + of text at start or end of line with a replace command. + Backslash quoted control characters \a, \b, \f, \t, and \v + recognized within sets. +
  • +
  • + Session files for SciTE. +
  • +
  • + Export as PDF command hidden in SciTE as it often failed. + Code still present so can be turned on by those willing to cope. +
  • +
  • + Bug fixed in HTML lexer handling % before > as end ASP + even when no start ASP encountered. + Bug fixed when scripts ended with a quoted string and + end tag was not seen. +
  • +
  • + Bug fixed on Windows where context menu key caused menu to + appear in corner of screen rather than within window. +
  • +
  • + Bug fixed in SciTE's Replace All command not processing + whole file when replace string longer than search string. +
  • +
  • + Bug fixed in SciTE's MRU list repeating entries if Ctrl+Tab + used when all entries filled. +
  • +
  • + ConvertEOLs call documentation fixed. +
  • +
+

+ Release 1.37 +

+
    +
  • + Released on 17 April 2001. +
  • +
  • + Bug fixed with scroll bars being invisible on GTK+ 1.2.9. +
  • +
  • + Scintilla and SciTE support find and replace using simple regular + expressions with tagged expressions. SciTE supports C '\' escapes + in the Find and Replace dialogs. + Replace in Selection available in SciTE. +
  • +
  • + Scintilla has a 'target' feature for replacing code rapidly without + causing display updates. +
  • +
  • + Scintilla and SciTE on GTK+ support file dropping from file managers + such as Nautilus and gmc. Files or other URIs dropped on Scintilla + result in a URIDropped notification. +
  • +
  • + Lexers may have separate Lex and Fold functions. +
  • +
  • + Lexer infrastructure improved to allow for plug in lexers and for referring + to lexers by name rather than by ID. +
  • +
  • + Ada lexer and support added. +
  • +
  • + Option in both Scintilla and SciTE to treat both left and right margin + as equally important when repositioning visible area in response to + caret movement. Default is to prefer visible area positioning which + minimizes the horizontal scroll position thus favouring the left margin. +
  • +
  • + Caret line highlighting. +
  • +
  • + Commands to delete from the caret to the end of line and + from the caret to the beginning of line. +
  • +
  • + SciTE has commands for inserting and removing block comments and + for inserting stream comments. +
  • +
  • + SciTE Director interface uses C++ '\' escapes to send control characters. +
  • +
  • + SciTE Director interface adds more commands including support for macros. +
  • +
  • + SciTE has menu options for recording and playing macros which are visible + when used with a companion program that supports these features. +
  • +
  • + SciTE has an Expand Abbreviation command. + Abbreviations are stored in a global abbrev.properties file. +
  • +
  • + SciTE has a Full Screen command to switch between a normal window + size and using the full screen. On Windows, the menu bar can be turned + off when in full screen mode. +
  • +
  • + SciTE has a Use monospaced font command to switch between the normal + set of fonts and one size of a particular fixed width font. +
  • +
  • + SciTE's use of tabs can be controlled for particular file names + as well as globally. +
  • +
  • + The contents of SciTE's status bar can be defined by a property and + include variables. On Windows, several status bar definitions can be active + with a click on the status bar cycling through them. +
  • +
  • + Copy as RTF command in SciTE on Windows to allow pasting + styled text into word processors. +
  • +
  • + SciTE can allow the use of non-alphabetic characters in + Complete Symbol lists and can automatically display this autocompletion + list when a trigger character such as '.' is typed. + Complete word can be set to pop up when the user is typing a word and + there is only one matching word in the document. +
  • +
  • + SciTE lists the imported properties files on a menu to allow rapid + access to them. +
  • +
  • + SciTE on GTK+ improvements to handling accelerator keys and focus + in dialogs. Message boxes respond to key presses without the Alt key as + they have no text entries to accept normal keystrokes. +
  • +
  • + SciTE on GTK+ sets the application icon. +
  • +
  • + SciTE allows setting the colours used to indicate the current + error line. +
  • +
  • + Variables within PHP strings have own style. Keyword list updated. +
  • +
  • + Keyword list for Lua updated for Lua 4.0. +
  • +
  • + Bug fixed in rectangular selection where rectangle still appeared + selected after using cursor keys to move caret. +
  • +
  • + Bug fixed in C++ lexer when deleting a '{' controlling a folded range + led to that range becoming permanently invisible. +
  • +
  • + Bug fixed in Batch lexer where comments were not recognized. +
  • +
  • + Bug fixed with undo actions coalescing into steps incorrectly. +
  • +
  • + Bug fixed with Scintilla on GTK+ positioning scroll bars 1 pixel + over the Scintilla window leading to their sides being chopped off. +
  • +
  • + Bugs fixed in SciTE when doing some actions led to the start + or end of the file being displayed rather than the current location. +
  • +
  • + Appearance of calltips fixed to look like document text including + any zoom factor. Positioned to be outside current line even when + multiple fonts and sizes used. +
  • +
  • + Bug fixed in Scintilla macro support where typing Enter caused both a newline + command and newline character insertion to be recorded. +
  • +
  • + Bug fixed in SciTE on GTK+ where focus was moving + between widgets incorrectly. +
  • +
  • + Bug fixed with fold symbols sometimes not updating when + the text changed. +
  • +
  • + Bugs fixed in SciTE's handling of folding commands. +
  • +
  • + Deprecated undo collection enumeration removed from API. +
  • +
+

+ Release 1.36 +

+
    +
  • + Released on 1 March 2001. +
  • +
  • + Scintilla supports GTK+ on Win32. +
  • +
  • + Some untested work on making Scintilla and SciTE 64 bit compatible. + For users on GTK+ this requires including Scintilla.h before + ScintillaWidget.h. +
  • +
  • + HTML lexer allows folding HTML. +
  • +
  • + New lexer for Avenue files which are used in the ESRI ArcView GIS. +
  • +
  • + DOS Batch file lexer has states for '@', external commands, variables and + operators. +
  • +
  • + C++ lexer can fold comments of /* .. */ form. +
  • +
  • + Better disabling of pop up menu items in Scintilla when in read-only mode. +
  • +
  • + Starting to move to Doxygen compatible commenting. +
  • +
  • + Director interface on Windows enables another application to control SciTE. +
  • +
  • + Opening SciTE on Windows 9x sped up greatly for some cases. +
  • +
  • + The command.build.directory property allows SciTE to run the build + command in a different directory to the source files. +
  • +
  • + SciTE on Windows allows setting foreground and background colours + for printed headers and footers. +
  • +
  • + Bug fixed in finding calltips in SciTE which led to no calltips for some identifiers. +
  • +
  • + Documentation added for lexers and for the extension and director interfaces. +
  • +
  • + SciTE menus rearranged with new View menu taking over some of the items that + were under the Options menu. Clear All Bookmarks command added. +
  • +
  • + Clear Output command in SciTE. +
  • +
  • + SciTE on Windows gains an Always On Top command. +
  • +
  • + Bug fixed in SciTE with attempts to define properties recursively. +
  • +
  • + Bug fixed in SciTE properties where only one level of substitution was done. +
  • +
  • + Bug fixed in SciTE properties where extensions were not being + matched in a case insensitive manner. +
  • +
  • + Bug fixed in SciTE on Windows where the Go to dialog displays the correct + line number. +
  • +
  • + In SciTE, if fold.on.open set then switching buffers also performs fold. +
  • +
  • + Bug fixed in Scintilla where ensuring a line was visible in the presence of folding + operated on the document line instead of the visible line. +
  • +
  • + SciTE command line processing modified to operate on arguments in order and in + two phases. First any arguments before the first file name are processed, then the + UI is opened, then the remaining arguments are processed. Actions defined for the + Director interface (currently only "open") may also be used on the command line. + For example, "SciTE -open:x.txt" will start SciTE and open x.txt. +
  • +
  • + Numbered menu items SciTE's Buffers menu and the Most Recently Used portion + of the File menu go from 1..0 rather than 0..9. +
  • +
  • + The tab bar in SciTE for Windows has numbers. + The tab.hide.one option hides the tab bar until there is more than one buffer open. +
  • +
+

+ Release 1.35 +

+
    +
  • + Released on 29 January 2001. +
  • +
  • + Rewritten and simplified widget code for the GTK+ version to enhance + solidity and make more fully compliant with platform norms. This includes more + normal handling of keystrokes so they are forwarded to containers correctly. +
  • +
  • + User defined lists can be shown. +
  • +
  • + Many fixes to the Perl lexer. +
  • +
  • + Pascal lexer handles comments more correctly. +
  • +
  • + C/C++/Java/JavaScript lexer has a state for line doc comments. +
  • +
  • + Error output lexer understands Sun CC messages. +
  • +
  • + Make file lexer has variable, preprocessor, and operator states. +
  • +
  • + Wider area given to an italics character that is at the end of a line to prevent it + being cut off. +
  • +
  • + Call to move the caret inside the currently visible area. +
  • +
  • + Paste Rectangular will space fill on the left hand side of the pasted text as + needed to ensure it is kept rectangular. +
  • +
  • + Cut and Paste Rectangular does nothing in read-only mode. +
  • +
  • + Undo batching changed so that a paste followed by typing creates two undo actions.. +
  • +
  • + A "visibility policy" setting for Scintilla determines which range of lines are displayed + when a particular line is moved to. Also exposed as a property in SciTE. +
  • +
  • + SciTE command line allows property settings. +
  • +
  • + SciTE has a View Output command to hide or show the output pane. +
  • +
  • + SciTE's Edit menu has been split in two with searching commands moved to a + new Search menu. Find Previous and Previous Bookmark are in the Search menu. +
  • +
  • + SciTE on Windows has options for setting print margins, headers and footers. +
  • +
  • + SciTE on Windows has tooltips for toolbar. +
  • +
  • + SciTE on GTK+ has properties for setting size of file selector. +
  • +
  • + Visual and audio cues in SciTE on Windows enhanced. +
  • +
  • + Fixed performance problem in SciTE for GTK+ by dropping the extra 3D + effect on the content windows. +
  • +
  • + Fixed problem in SciTE where choosing a specific lexer then meant + that no lexer was chosen when files opened. +
  • +
  • + Default selection colour changed to be visible on low colour displays. +
  • +
  • + Fixed problems with automatically reloading changed documents in SciTE on + Windows. +
  • +
  • + Fixed problem with uppercase file extensions in SciTE. +
  • +
  • + Fixed some problems when using characters >= 128, some of which were being + incorrectly treated as spaces. +
  • +
  • + Fixed handling multiple line tags, non-inline scripts, and XML end tags /> in HTML/XML lexer. +
  • +
  • + Bookmarks in SciTE no longer disappear when switching between buffers. +
  • +
+

+ Release 1.34 +

+
    +
  • + Released on 28 November 2000. +
  • +
  • + Pascal lexer. +
  • +
  • + Export as PDF in SciTE. +
  • +
  • + Support for the OpenVMS operating system in SciTE. +
  • +
  • + SciTE for GTK+ can check for another instance of SciTE + editing a file and switch to it rather than open a second instance + on one file. +
  • +
  • + Fixes to quoting and here documents in the Perl lexer. +
  • +
  • + SciTE on Windows can give extra visual and audio cues when a + warning is shown or find restarts from beginning of file. +
  • +
  • + Open Selected Filename command in SciTE. Also understands some + warning message formats. +
  • +
  • + Wider area for line numbers when printing. +
  • +
  • + Better scrolling performance on GTK+. +
  • +
  • + Fixed problem where rectangles with negative coordinates were + invalidated leading to trouble with platforms that use + unsigned coordinates. +
  • +
  • + GTK+ Scintilla uses more compliant signalling code so that keyboard + events should propagate to containers. +
  • +
  • + Bug fixed with opening full or partial paths. +
  • +
  • + Improved handling of paths in error messages in SciTE. +
  • +
  • + Better handling of F6 in SciTE. +
  • +
+

+ Release 1.33 +

+
    +
  • + Released on 6 November 2000. +
  • +
  • + XIM support for the GTK+ version of Scintilla ensures that more non-English + characters can be typed. +
  • +
  • + Caret may be 1, 2, or 3 pixels wide. +
  • +
  • + Cursor may be switched to wait image during lengthy processing. +
  • +
  • + Scintilla's internal focus flag is exposed for clients where focus is handled in + complex ways. +
  • +
  • + Error status defined for Scintilla to hold indication that an operation failed and the reason + for that failure. No detection yet implemented but clients may start using the interface + so as to be ready for when it does. +
  • +
  • + Context sensitive help in SciTE. +
  • +
  • + CurrentWord property available in SciTE holding the value of the word the + caret is within or near. +
  • +
  • + Apache CONF file lexer. +
  • +
  • + Changes to Python lexer to allow 'as' as a context sensitive keyword and the + string forms starting with u, r, and ur to be recognized. +
  • +
  • + SCN_POSCHANGED notification now working and SCN_PAINTED notification added. +
  • +
  • + Word part movement commands for cursoring between the parts of reallyLongCamelIdentifiers and + other_ways_of_making_words. +
  • +
  • + When text on only one line is selected, Shift+Tab moves to the previous tab stop. +
  • +
  • + Tab control available for Windows version of SciTE listing all the buffers + and making it easy to switch between them. +
  • +
  • + SciTE can be set to automatically determine the line ending type from the contents of a + file when it is opened. +
  • +
  • + Dialogs in GTK+ version of SciTE made more modal and have accelerator keys. +
  • +
  • + Find in Files command in GTK+ version of SciTE allows choice of directory. +
  • +
  • + On Windows, multiple files can be opened at once. +
  • +
  • + SciTE source broken up into more files. +
  • +
  • + Scintilla headers made safe for C language, not just C++. +
  • +
  • + New printing modes - force background to white and force default background to white. +
  • +
  • + Automatic unfolding not occurring when Enter pressed at end of line bug fixed. +
  • +
  • + Bugs fixed in line selection. +
  • +
  • + Bug fixed with escapes in PHP strings in the HTML lexer. +
  • +
  • + Bug fixed in SciTE for GTK+ opening files when given full paths. +
  • +
  • + Bug fixed in autocompletion where user backspaces into existing text. +
  • +
  • + Bugs fixed in opening files and ensuring they are saved before running. + A case bug also fixed here. +
  • +
+

+ Release 1.32 +

+
    +
  • + Released on 8 September 2000. +
  • +
  • + Fixes bugs in complete word and related code. Protection against a bug when + receiving a bad argument. +
  • +
+

+ Release 1.31 +

+
    +
  • + Released on 6 September 2000. +
  • +
  • + Scintilla is available as a COM control from the scintillactrl module in CVS. +
  • +
  • + Style setting to underline text. Exposed in SciTE as "underlined". +
  • +
  • + Style setting to make text invisible. +
  • +
  • + SciTE has an extensibility interface that can be used to implement features such as + a scripting language or remote control. An example use of this is the extlua module + available from CVS which allows SciTE to be scripted in Lua. +
  • +
  • + Many minor fixes to all of the lexers. +
  • +
  • + New lexer for diff and patch files. +
  • +
  • + Error message lexer understands Perl error messages. +
  • +
  • + C/C++/Java lexer now supports C#, specifically verbatim strings and + @ quoting of identifiers that are the same as keywords. SciTE has + a set of keywords for C# and a build command set up for C#. +
  • +
  • + Scintilla property to see whether in overtype or insert state. +
  • +
  • + PosChanged notification fired when caret moved. +
  • +
  • + Comboboxes in dialogs in SciTE on Windows can be horizontally scrolled. +
  • +
  • + Autocompletion and calltips can treat the document as case sensitive or + case insensitive. +
  • +
  • + Autocompletion can be set to automatically choose the only + element in a single element list. +
  • +
  • + Set of characters that automatically complete an autocompletion list + can be set. +
  • +
  • + SciTE command to display calltip - useful when dropped because of + editing. +
  • +
  • + SciTE has a Revert command to go back to the last saved version. +
  • +
  • + SciTE has an Export as RTF command. Save as HTML is renamed + to Export as HTML and is located on the Export sub menu. +
  • +
  • + SciTE command "Complete Word" searches document for any + words starting with characters before caret. +
  • +
  • + SciTE options for changing aspects of the formatting of files exported + as HTML or RTF. +
  • +
  • + SciTE "character.set" option for choosing the character + set for all fonts. +
  • +
  • + SciTE has a "Toggle all folds" command. +
  • +
  • + The makefiles have changed. The makefile_vc and + makefile_bor files in scintilla/win32 and scite/win32 have been + merged into scintilla/win32/scintilla.mak and scite/win32/scite.mak. + DEBUG may be defined for all make files and this will turn on + assertions and for some make files will choose other debugging + options. +
  • +
  • + To make debugging easier and allow good use of BoundsChecker + there is a Visual C++ project file in scite/boundscheck that builds + all of Scintilla and SciTE into one executable. +
  • +
  • + The size of the SciTE output window can be set with the + output.horizontal.size and output.vertical.size settings. +
  • +
  • + SciTE status bar indicator for insert or overwrite mode. +
  • +
  • + Performance improvements to autocompletion and calltips. +
  • +
  • + A caret redraw problem when undoing is fixed. +
  • +
  • + Crash with long lines fixed. +
  • +
  • + Bug fixed with merging markers when lines merged. +
  • +
+

+ Release 1.30 +

+
    +
  • + Released on 26 July 2000. +
  • +
  • + Much better support for PHP which is now an integral part of the HTML support. +
  • +
  • + Start replacement of Windows-specific APIs with cross platform APIs. + In 1.30, the new APIs are introduced but the old APIs are still available. + For the GTK+ version, may have to include "WinDefs.h" explicitly to + use the old APIs. +
  • +
  • + "if" and "import" statements in SciTE properties files allows modularization into + language-specific properties files and choices based upon platform. + This means that SciTE is delivered with 9 language-specific properties files + as well as the standard SciTEGlobal.properties file. +
  • +
  • + Much lower resource usage on Windows 9x. +
  • +
  • + "/p" option in SciTE on Windows for printing a file and then exiting. +
  • +
  • + Options for printing with inverted brightness (when the screen is set to use + a dark background) and to force black on white printing. +
  • +
  • + Option for printing magnified or miniaturized from screen settings. +
  • +
  • + In SciTE, Ctrl+F3 and Ctrl+Shift+F3 find the selection in the forwards and backwards + directions respectively. +
  • +
  • + Auto-completion lists may be set to cancel when the cursor goes before + its start position or before the start of string being completed. +
  • +
  • + Auto-completion lists automatically size more sensibly. +
  • +
  • + SCI_CLEARDOCUMENTSTYLE zeroes all style bytes, ensures all + lines are shown and deletes all folding information. +
  • +
  • + On Windows, auto-completion lists are visually outdented rather than indented. +
  • +
  • + Close all command in SciTE. +
  • +
  • + On Windows multiple files can be dragged into SciTE. +
  • +
  • + When saving a file, the SciTE option save.deletes.first deletes it before doing the save. + This allows saving with a different capitalization on Windows. +
  • +
  • + When use tabs option is off pressing the tab key inserts spaces. +
  • +
  • + Bug in indicators leading to extra line drawn fixed. +
  • +
+

+ Release 1.28 +

+
    +
  • + Released on 27 June 2000. +
  • +
  • + Fixes crash in indentation guides when indent size set to 0. +
  • +
  • + Fixes to installation on GTK+/Linux. User properties file on GTK+ has a dot at front of name: + .SciTEUser.properties. Global properties file location configurable at compile time + defaulting to $prefix/share/scite. $prefix determined from Gnome if present else its + /usr/local and can be overridden by installer. Gnome menu integration performed in + make install if Gnome present. +
  • +
+

+ Release 1.27 +

+
    +
  • + Released on 23 June 2000. +
  • +
  • + Indentation guides. View whitespace mode may be set to not display whitespace + in indentation. +
  • +
  • + Set methods have corresponding gets for UndoCollection, BufferedDraw, + CodePage, UsePalette, ReadOnly, CaretFore, and ModEventMask. +
  • +
  • + Caret is continuously on rather than blinking while typing or holding down + delete or backspace. And is now always shown if non blinking when focused on GTK+. +
  • +
  • + Bug fixed in SciTE with file extension comparison now done in case insensitive way. +
  • +
  • + Bugs fixed in SciTE's file path handling on Windows. +
  • +
  • + Bug fixed with preprocessor '#' last visible character causing hang. +
  • +
+

+ Release 1.26 +

+
    +
  • + Released on 13 June 2000. +
  • +
  • + Support for the Lua language in both Scintilla and SciTE. +
  • +
  • + Multiple buffers may be open in SciTE. +
  • +
  • + Each style may have a character set configured. This may determine + the characters that are displayed by the style. +
  • +
  • + In the C++ lexer, lexing of preprocessor source may either treat it all as being in + the preprocessor class or only the initial # and preprocessor command word as + being in the preprocessor class. +
  • +
  • + Scintilla provides SCI_CREATEDOCUMENT, SCI_ADDREFDOCUMENT, and + SCI_RELEASEDOCUMENT to make it easier for a container to deal with multiple + documents. +
  • +
  • + GTK+ specific definitions in Scintilla.h were removed to ScintillaWidget.h. All GTK+ clients will need to + #include "ScintillaWidget.h". +
  • +
  • + For GTK+, tools can be executed in the background by setting subsystem to 2. +
  • +
  • + Keys in the properties files are now case sensitive. This leads to a performance increase. +
  • +
  • + Menu to choose which lexer to use on a file. +
  • +
  • + Tab size dialog on Windows. +
  • +
  • + File dialogs enlarged on GTK+. +
  • +
  • + Match Brace command bound to Ctrl+E on both platforms with Ctrl+] a synonym on Windows. + Ctrl+Shift+E is select to matching brace. Brace matching tries to match to either the inside or the + outside, depending on whether the cursor is inside or outside the braces initially. + View End of Line bound to Ctrl+Shift+O. +
  • +
  • + The Home key may be bound to move the caret to either the start of the line or the start of the + text on the line. +
  • +
  • + Visual C++ project file for SciTE. +
  • +
  • + Bug fixed with current x location after Tab key. +
  • +
  • + Bug fixed with hiding fold margin by setting fold.margin.width to 0. +
  • +
  • + Bugs fixed with file name confusion on Windows when long and short names used, or different capitalizations, + or relative paths. +
  • +
+

+ Release 1.25 +

+
    +
  • + Released on 9 May 2000. +
  • +
  • + Some Unicode support on Windows. Treats buffer and API as UTF-8 and displays + through UCS-2 of Windows. +
  • +
  • + Automatic indentation. Indentation size can be different to tab size. +
  • +
  • + Tool bar. +
  • +
  • + Status bar now on Windows as well as GTK+. +
  • +
  • + Input fields in Find and Replace dialogs now have history on both Windows and + GTK+. +
  • +
  • + Auto completion list items may be separated by a chosen character to allow spaces + in items. The selected item may be changed through the API. +
  • +
  • + Horizontal scrollbar can be turned off. +
  • +
  • + Property to remove trailing spaces when saving file. +
  • +
  • + On Windows, changed font size calculation to be more compatible with + other applications. +
  • +
  • + On GTK+, SciTE's global properties files are looked for in the directory specified in the + SCITE_HOME environment variable if it is set. This allows hiding in a dot directory. +
  • +
  • + Keyword lists in SciTE updated for JavaScript to include those destined to be used in + the future. IDL includes XPIDL keywords as well as MSIDL keywords. +
  • +
  • + Zoom level can be set and queried through API. +
  • +
  • + New notification sent before insertions and deletions. +
  • +
  • + LaTeX lexer. +
  • +
  • + Fixes to folding including when deletions and additions are performed. +
  • +
  • + Fix for crash with very long lines. +
  • +
  • + Fix to affect all of rectangular selections with deletion and case changing. +
  • +
  • + Removed non-working messages that had been included only for Richedit compatibility. +
  • +
+

+ Release 1.24 +

+
    +
  • + Released on 29 March 2000. +
  • +
  • + Added lexing of IDL based on C++ lexer with extra UUID lexical class. +
  • +
  • + Functions and associated keys for Line Delete, Line Cut, Line Transpose, + Selection Lower Case and Selection Upper Case. +
  • +
  • + Property setting for SciTE, eol.mode, chooses initial state of line end characters. +
  • +
  • + Fixed bugs in undo history with small almost-contiguous changes being incorrectly coalesced. +
  • +
  • + Fixed bugs with incorrect expansion of ContractionState data structures causing crash. +
  • +
  • + Fixed bugs relating to null fonts. +
  • +
  • + Fixed bugs where recolourization was not done sometimes when required. +
  • +
  • + Fixed compilation problems with SVector.h. +
  • +
  • + Fixed bad setting of fold points in Python. +
  • +
+

+ Release 1.23 +

+
    +
  • + Released on 21 March 2000. +
  • +
  • + Directory structure to separate on basis of product (Scintilla, SciTE, DMApp) + and environment (Cross-platform, Win32, GTK+). +
  • +
  • + Download packaging to allow download of the source or platform dependent executables. +
  • +
  • + Source code now available from CVS at SourceForge. +
  • +
  • + Very simple Windows-only demonstration application DMApp is available from cvs as dmapp. +
  • +
  • + Lexing functionality may optionally be included in Scintilla rather than be provided by + the container. +
  • +
  • + Set of lexers included is determined at link time by defining which of the Lex* object files + are linked in. +
  • +
  • + On Windows, the SciLexer.DLL extends Scintilla.DLL with the standard lexers. +
  • +
  • + Enhanced HTML lexer styles embedded VBScript and Python. + ASP segments are styled and ASP scripts in JavaScript, VBScript and Python are styled. +
  • +
  • + PLSQL and PHP supported. +
  • +
  • + Maximum number of lexical states extended to 128. +
  • +
  • + Lexers may store per line parse state for multiple line features such as ASP script language choice. +
  • +
  • + Lexing API simplified. +
  • +
  • + Project file for Visual C++. +
  • +
  • + Can now cycle through all recent files with Ctrl+Tab in SciTE. +
  • +
  • + Bookmarks in SciTE. +
  • +
  • + Drag and drop copy works when dragging to the edge of the selection. +
  • +
  • + Fixed bug with value sizes in properties file. +
  • +
  • + Fixed bug with last line in properties file not being used. +
  • +
  • + Bug with multiple views of one document fixed. +
  • +
  • + Keypad now works on GTK+. +
  • +
+

+ Release 1.22 +

+
    +
  • + Released on 27 February 2000. +
  • +
  • + wxWindows platform defined. + Implementation for wxWindows will be available separately + from main Scintilla distribution. +
  • +
  • + Line folding in Scintilla. +
  • +
  • + SciTE performs syntax directed folding for C/C++/Java/JavaScript and for Python. +
  • +
  • + Optional macro recording support. +
  • +
  • + User properties file (SciTEUser.properties) allows for customization by the user + that is not overwritten with each installation of SciTE. +
  • +
  • + Python lexer detects and highlights inconsistent indentation. +
  • +
  • + Margin API made more orthogonal. SCI_SETMARGINWIDTH and SCI_SETLINENUMBERWIDTH + are deprecated in favour of this new API. +
  • +
  • + Margins may be made sensitive to forward mouse click events to container. +
  • +
  • + SQL lexer and styles included. +
  • +
  • + Perl lexer handles regular expressions better. +
  • +
  • + Caret policy determines how closely caret is tracked by visible area. +
  • +
  • + New marker shapes: arrow pointing down, plus and minus. +
  • +
  • + Optionally display full path in title rather than just file name. +
  • +
  • + Container is notified when Scintilla gains or loses focus. +
  • +
  • + SciTE handles focus in a more standard way and applies the main + edit commands to the focused pane. +
  • +
  • + Container is notified when Scintilla determines that a line needs to be made visible. +
  • +
  • + Document watchers receive notification when document about to be deleted. +
  • +
  • + Document interface allows access to list of watchers. +
  • +
  • + Line end determined correctly for lines ending with only a '\n'. +
  • +
  • + Search variant that searches form current selection and sets selection. +
  • +
  • + SciTE understands format of diagnostic messages from WScript. +
  • +
  • + SciTE remembers top line of window for each file in MRU list so switching to a recent file + is more likely to show the same text as when the file was previously visible. +
  • +
  • + Document reference count now initialized correctly. +
  • +
  • + Setting a null document pointer creates an empty document. +
  • +
  • + WM_GETTEXT can no longer overrun buffer. +
  • +
  • + Polygon drawing bug fixed on GTK+. +
  • +
  • + Java and JavaScript lexers merged into C++ lexer. +
  • +
  • + C++ lexer indicates unterminated strings by colouring the end of the line + rather than changing the rest of the file to string style. This is less + obtrusive and helps the folding. +
  • +
+

+ Release 1.21 +

+
    +
  • + Released on 2 February 2000. +
  • +
  • + Blank margins on left and right side of text. +
  • +
  • + SCN_CHECKBRACE renamed SCN_UPDATEUI and made more efficient. +
  • +
  • + SciTE source code refactored into platform independent and platform specific classes. +
  • +
  • + XML and Perl subset lexers in SciTE. +
  • +
  • + Large improvement to lexing speed. +
  • +
  • + A new subsystem, 2, allows use of ShellExec on Windows. +
  • +
  • + Borland compatible makefile. +
  • +
  • + Status bar showing caret position in GTK+ version of SciTE. +
  • +
  • + Bug fixes to selection drawing when part of selection outside window, mouse release over + scroll bars, and scroll positioning after deletion. +
  • +
+

+ Release 1.2 +

+
    +
  • + Released on 21 January 2000. +
  • +
  • + Multiple views of one document. +
  • +
  • + Rectangular selection, cut, copy, paste, drag and drop. +
  • +
  • + Long line indication. +
  • +
  • + Reverse searching +
  • +
  • + Line end conversion. +
  • +
  • + Generic autocompletion and calltips in SciTE. +
  • +
  • + Call tip background colour can be set. +
  • +
  • + SCI_MARKERPREV for moving to a previous marker. +
  • +
  • + Caret kept more within window where possible. +
  • +
+

+ Release 1.15 +

+
    +
  • + Released on 15 December 1999. +
  • +
  • + Brace highlighting and badlighting (for mismatched braces). +
  • +
  • + Visible line ends. +
  • +
  • + Multiple line call tips. +
  • +
  • + Printing now works from SciTE on Windows. +
  • +
  • + SciTE has a global "*" lexer style that is used as the basis for all the lexers' styles. +
  • +
  • + Fixes some warnings on GTK+ 1.2.6. +
  • +
  • + Better handling of modal dialogs on GTK+. +
  • +
  • + Resize handle drawn on pane splitter in SciTE on GTK+ so it looks more like a regular GTK+ + *paned widget. +
  • +
  • + SciTE does not place window origin offscreen if no properties file found on GTK+. +
  • +
  • + File open filter remembered in SciTE on Windows. +
  • +
  • + New mechanism using style numbers 32 to 36 standardizes the setting of styles for brace + highlighting, brace badlighting, line numbers, control characters and the default style. +
  • +
  • + Old messages SCI_SETFORE .. SCI_SETFONT have been replaced by the default style 32. The old + messages are deprecated and will disappear in a future version. +
  • +
+

+ Release 1.14 +

+
    +
  • + Released on 20 November 1999. +
  • +
  • + Fixes a scrolling bug reported on GTK+. +
  • +
+

+ Release 1.13 +

+
    +
  • + Released on 18 November 1999. +
  • +
  • + Fixes compilation problems with the mingw32 GCC 2.95.2 on Windows. +
  • +
  • + Control characters are now visible. +
  • +
  • + Performance has improved, particularly for scrolling. +
  • +
  • + Windows RichEdit emulation is more accurate. This may break client code that uses these + messages: EM_GETLINE, EM_GETLINECOUNT, EM_EXGETSEL, EM_EXSETSEL, EM_EXLINEFROMCHAR, + EM_LINELENGTH, EM_LINEINDEX, EM_CHARFROMPOS, EM_POSFROMCHAR, and EM_GETTEXTRANGE. +
  • +
  • + Menus rearranged and accelerator keys set for all static items. +
  • +
  • + Placement of space indicators in view whitespace mode is more accurate with some fonts. +
  • +
+

+ Release 1.12 +

+
    +
  • + Released on 9 November 1999. +
  • +
  • + Packaging error in 1.11 meant that the compilation error was not fixed in that release. + Linux/GTK+ should compile with GCC 2.95 this time. +
  • +
+

+ Release 1.11 +

+
    +
  • + Released on 7 November 1999. +
  • +
  • + Fixed a compilation bug in ScintillaGTK.cxx. +
  • +
  • + Added a README file to explain how to build. +
  • +
  • + GTK+/Linux downloads now include documentation. +
  • +
  • + Binary only Sc1.EXE one file download for Windows. +
  • +
+

+ Release 1.1 +

+
    +
  • + Released on 6 November 1999. +
  • +
  • + Major restructuring for better modularity and platform independence. +
  • +
  • + Inter-application drag and drop. +
  • +
  • + Printing support in Scintilla on Windows. +
  • +
  • + Styles can select colouring to end of line. This can be used when a file contains more than + one language to differentiate between the areas in each language. An example is the HTML + + JavaScript styling in SciTE. +
  • +
  • + Actions can be grouped in the undo stack, so they will be undone together. This grouping is + hierarchical so higher level actions such as replace all can be undone in one go. Call to + discover whether there are any actions to redo. +
  • +
  • + The set of characters that define words can be changed. +
  • +
  • + Markers now have identifiers and can be found and deleted by their identifier. The empty + marker type can be used to make a marker that is invisible and which is only used to trace + where a particular line moves to. +
  • +
  • + Double click notification. +
  • +
  • + HTML styling in SciTE also styles embedded JavaScript. +
  • +
  • + Additional tool commands can be added to SciTE. +
  • +
  • + SciTE option to allow reloading if changed upon application activation and saving on + application deactivation. Not yet working on GTK+ version. +
  • +
  • + Entry fields in search dialogs remember last 10 user entries. Not working in all cases in + Windows version. +
  • +
  • + SciTE can save a styled copy of the current file in HTML format. As SciTE does not yet + support printing, this can be used to print a file by then using a browser to print the + HTML file. +
  • +
+

+ Release 1.02 +

+
    +
  • + Released on 1 October 1999. +
  • +
  • + GTK+ version compiles with GCC 2.95. +
  • +
  • + Properly deleting objects when window destroyed under GTK+. +
  • +
  • + If the selection is not empty backspace deletes the selection. +
  • +
  • + Some X style middle mouse button handling for copying the primary selection to and from + Scintilla. Does not work in all cases. +
  • +
  • + HTML styling in SciTE. +
  • +
  • + Stopped dirty flag being set in SciTE when results pane modified. +
  • +
+

+ Release 1.01 +

+
    +
  • + Released on 28 September 1999. +
  • +
  • + Better DBCS support on Windows including IME. +
  • +
  • + Wheel mouse support for scrolling and zooming on Windows. Zooming with Ctrl+KeypadPlus and + Ctrl+KeypadMinus. +
  • +
  • + Performance improvements especially on GTK+. +
  • +
  • + Caret blinking and settable colour on both GTK+ and Windows. +
  • +
  • + Drag and drop within a Scintilla window. On Windows, files can be dragged into SciTE. +
  • +
+

+ Release 1.0 +

+
    +
  • + Released on 17 May 1999. +
  • +
  • + Changed name of "Tide" to "SciTE" to avoid clash with a TCL based IDE. "SciTE" is a + SCIntilla based Text Editor and is Latin meaning something like "understanding in a neat + way" and is also an Old English version of the word "shit". +
  • +
  • + There is a SCI_AUTOCSTOPS message for defining a string of characters that will stop + autocompletion mode. Autocompletion mode is cancelled when any cursor movement occurs apart + from backspace. +
  • +
  • + GTK+ version now splits horizontally as well as vertically and all dialogs cancel when the + escape key is pressed. +
  • +
+

+ Beta release 0.93 +

+
    +
  • + Released on 12 May 1999. +
  • +
  • + A bit more robust than 0.92 and supports SCI_MARKERNEXT message. +
  • +
+

+ Beta release 0.92 +

+
    +
  • + Released on 11 May 1999. +
  • +
  • + GTK+ version now contains all features of Windows version with some very small differences. + Executing programs works much better now. +
  • +
  • + New palette code to allow more colours to be displayed in 256 colour screen modes. A line + number column can be displayed to the left of the selection margin. +
  • +
  • + The code that maps from line numbers to text positions and back has been completely + rewritten to be faster, and to allow markers to move with the text. +
  • +
+

+ Beta release 0.91 +

+
    +
  • + Released on 30 April 1999, containing fixes to text measuring to make Scintilla work better + with bitmap fonts. Also some small fixes to make compiling work with Visual C++. +
  • +
+

+ Beta release 0.90 +

+
    +
  • + Released on 29 April 1999, containing working GTK+/Linux version. +
  • +
  • + The Java, C++ and Python lexers recognize operators as distinct from default allowing them + to be highlighted. +
  • +
+

+ Beta release 0.82 +

+
    +
  • + Released on 1 April 1999, to fix a problem with handling the Enter key in PythonWin. Also + fixes some problems with cmd key mapping. +
  • +
+

+ Beta release 0.81 +

+
    +
  • + Released on 30th March 1999, containing bug fixes and a few more features. +
  • +
  • + Static linking supported and Tidy.EXE, a statically linked version of Tide.EXE. Changes to + compiler flags in the makefiles to optimize for size. +
  • +
  • + Scintilla supports a 'savepoint' in the undo stack which can be set by the container when + the document is saved. Notifications are sent to the container when the savepoint is + entered or left, allowing the container to display a dirty indicator and change its + menus. +
  • +
  • + When Scintilla is set to read-only mode, a notification is sent to the container should the + user try to edit the document. This can be used to check the document out of a version + control system. +
  • +
  • + There is an API for setting the appearance of indicators. +
  • +
  • + The keyboard mapping can be redefined or removed so it can be implemented completely by the + container. All of the keyboard commands are now commands which can be sent by the + container. +
  • +
  • + A home command like Visual C++ with one hit going to the start of the text on the line and + the next going to the left margin is available. I do not personally like this but my + fingers have become trained to it by much repetition. +
  • +
  • + SCI_MARKERDELETEALL has an argument in wParam which is the number of the type marker to + delete with -1 performing the old action of removing all marker types. +
  • +
  • + Tide now understands both the file name and line numbers in error messages in most cases. +
  • +
  • + Tide remembers the current lines of files in the recently used list. +
  • +
  • + Tide has a Find in Files command. +
  • +
+

+ Beta release 0.80 +

+
    +
  • + This was the first public release on 14th March 1999, containing a mostly working Win32 + Scintilla DLL and Tide EXE. +
  • +
+

+ Beta releases of SciTE were called Tide +

+ + diff --git a/src/lexilla/doc/LexillaLogo.png b/src/lexilla/doc/LexillaLogo.png new file mode 100644 index 000000000..fe78f4988 Binary files /dev/null and b/src/lexilla/doc/LexillaLogo.png differ diff --git a/src/lexilla/doc/LexillaLogo2x.png b/src/lexilla/doc/LexillaLogo2x.png new file mode 100644 index 000000000..65a99a6b4 Binary files /dev/null and b/src/lexilla/doc/LexillaLogo2x.png differ diff --git a/src/lexilla/examples/CheckLexilla/CheckLexilla.c b/src/lexilla/examples/CheckLexilla/CheckLexilla.c new file mode 100644 index 000000000..3fd5aa297 --- /dev/null +++ b/src/lexilla/examples/CheckLexilla/CheckLexilla.c @@ -0,0 +1,144 @@ +// Lexilla lexer library use example +/** @file CheckLexilla.c + ** Check that Lexilla.h works. + **/ +// Copyright 2021 by Neil Hodgson +// This file is in the public domain. +// If the public domain is not possible in your location then it can also be used under the same +// license as Scintilla. https://www.scintilla.org/License.txt + +/* Build and run + + Win32 +gcc CheckLexilla.c -I ../../include -o CheckLexilla +CheckLexilla +CheckLexilla ../SimpleLexer/SimpleLexer.dll + + Win32 Visual C++ +cl CheckLexilla.c -I ../../include -Fe: CheckLexilla +CheckLexilla +CheckLexilla ../SimpleLexer/SimpleLexer.dll + + macOS +clang CheckLexilla.c -I ../../include -o CheckLexilla +./CheckLexilla +./CheckLexilla ../SimpleLexer/SimpleLexer.dylib + + Linux +gcc CheckLexilla.c -I ../../include -ldl -o CheckLexilla +./CheckLexilla +./CheckLexilla ../SimpleLexer/SimpleLexer.so + +While principally meant for compilation as C to act as an example of using Lexilla +from C it can also be built as C++. + +Warnings are intentionally shown for the deprecated typedef LexerNameFromIDFn when compiled with +GCC or Clang or as C++. + +*/ + +#include + +#if defined(_WIN32) +#include +#else +#include +#endif + +#if defined(__cplusplus) +#include "ILexer.h" +#endif + +#include "Lexilla.h" + +#if defined(__cplusplus) +using namespace Lexilla; +#endif + +#if defined(_WIN32) +typedef FARPROC Function; +typedef HMODULE Module; +#else +typedef void *Function; +typedef void *Module; +#endif + +static Function FindSymbol(Module m, const char *symbol) { +#if defined(_WIN32) + return GetProcAddress(m, symbol); +#else + return dlsym(m, symbol); +#endif +} + +int main(int argc, char *argv[]) { + char szLexillaPath[] = "../../bin/" LEXILLA_LIB LEXILLA_EXTENSION; + const char *libPath = szLexillaPath; + if (argc > 1) { + libPath = argv[1]; + } +#if defined(_WIN32) + Module lexillaLibrary = LoadLibraryA(libPath); +#else + Module lexillaLibrary = dlopen(libPath, RTLD_LAZY); +#endif + + printf("Opened %s -> %p.\n", libPath, lexillaLibrary); + if (lexillaLibrary) { + GetLexerCountFn lexerCount = (GetLexerCountFn)FindSymbol(lexillaLibrary, LEXILLA_GETLEXERCOUNT); + if (lexerCount) { + int nLexers = lexerCount(); + printf("There are %d lexers.\n", nLexers); + GetLexerNameFn lexerName = (GetLexerNameFn)FindSymbol(lexillaLibrary, LEXILLA_GETLEXERNAME); + for (int i = 0; i < nLexers; i++) { + char name[100] = ""; + lexerName(i, name, sizeof(name)); + printf("%s ", name); + } + printf("\n"); + + GetLexerFactoryFn lexerFactory = (GetLexerFactoryFn)FindSymbol(lexillaLibrary, LEXILLA_GETLEXERFACTORY); + LexerFactoryFunction lexerFactory4 = lexerFactory(4); // 4th entry is "as" which is an object lexer so works + printf("Lexer factory 4 -> %p.\n", lexerFactory4); + + CreateLexerFn lexerCreate = (CreateLexerFn)FindSymbol(lexillaLibrary, LEXILLA_CREATELEXER); + ILexer5 *lexerCpp = lexerCreate("cpp"); + printf("Created cpp lexer -> %p.\n", lexerCpp); + + LexerNameFromIDFn lexerNameFromID = (LexerNameFromIDFn)FindSymbol(lexillaLibrary, LEXILLA_LEXERNAMEFROMID); + if (lexerNameFromID) { + const char *lexerNameCpp = lexerNameFromID(3); // SCLEX_CPP=3 + if (lexerNameCpp) { + printf("Lexer name 3 -> %s.\n", lexerNameCpp); + } else { + printf("Lexer name 3 not available.\n"); + } + } else { + printf("Lexer name from ID not supported.\n"); + } + + GetLibraryPropertyNamesFn libraryProperties = (GetLibraryPropertyNamesFn)FindSymbol(lexillaLibrary, LEXILLA_GETLIBRARYPROPERTYNAMES); + if (libraryProperties) { + const char *names = libraryProperties(); + printf("Property names '%s'.\n", names); + } else { + printf("Property names not supported.\n"); + } + + SetLibraryPropertyFn librarySetProperty = (SetLibraryPropertyFn)FindSymbol(lexillaLibrary, LEXILLA_SETLIBRARYPROPERTY); + if (librarySetProperty) { + librarySetProperty("key", "value"); + } else { + printf("Set property not supported.\n"); + } + + GetNameSpaceFn libraryNameSpace = (GetLibraryPropertyNamesFn)FindSymbol(lexillaLibrary, LEXILLA_GETNAMESPACE); + if (libraryNameSpace) { + const char *nameSpace = libraryNameSpace(); + printf("Name space '%s'.\n", nameSpace); + } else { + printf("Name space not supported.\n"); + } + } + } +} diff --git a/src/lexilla/examples/SimpleLexer/SimpleLexer.cxx b/src/lexilla/examples/SimpleLexer/SimpleLexer.cxx new file mode 100644 index 000000000..652de88f6 --- /dev/null +++ b/src/lexilla/examples/SimpleLexer/SimpleLexer.cxx @@ -0,0 +1,123 @@ +// A simple lexer +/** @file SimpleLexer.cxx + ** A lexer that follows the Lexilla protocol to allow it to be used from Lexilla clients like SciTE. + ** The lexer applies alternating styles (0,1) to bytes of the text. + **/ +// Copyright 2021 by Neil Hodgson +// This file is in the public domain. +// If the public domain is not possible in your location then it can also be used under the same +// license as Scintilla. https://www.scintilla.org/License.txt + +// Windows/MSVC +// cl -std:c++17 -EHsc -LD -I ../../../scintilla/include -I ../../include -I ../../lexlib SimpleLexer.cxx ../../lexlib/*.cxx + +// macOS/clang +// clang++ -dynamiclib --std=c++17 -I ../../../scintilla/include -I ../../include -I ../../lexlib SimpleLexer.cxx ../../lexlib/*.cxx -o SimpleLexer.dylib + +// Linux/g++ +// g++ -fPIC -shared --std=c++17 -I ../../../scintilla/include -I ../../include -I ../../lexlib SimpleLexer.cxx ../../lexlib/*.cxx -o SimpleLexer.so + +/* It can be demonstrated in SciTE like this, substituting the actual shared library location as lexilla.path: +lexilla.path=.;C:\u\hg\lexilla\examples\SimpleLexer\SimpleLexer.dll +lexer.*.xx=simple +style.simple.1=fore:#FF0000 +*/ + +#include +#include +#include + +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" +// Lexilla.h should not be included here as it declares statically linked functions without the __declspec( dllexport ) + +#include "WordList.h" +#include "PropSetSimple.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "LexerBase.h" + +using namespace Scintilla; +using namespace Lexilla; + +class LexerSimple : public LexerBase { +public: + LexerSimple() { + } + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override { + try { + Accessor astyler(pAccess, &props); + if (length > 0) { + astyler.StartAt(startPos); + astyler.StartSegment(startPos); + for (unsigned int k=0; kSetErrorStatus(SC_STATUS_FAILURE); + } + } + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override { + } + + static ILexer5 *LexerFactorySimple() { + try { + return new LexerSimple(); + } catch (...) { + // Should not throw into caller as may be compiled with different compiler or options + return nullptr; + } + } +}; + +#if defined(_WIN32) +#define EXPORT_FUNCTION __declspec(dllexport) +#define CALLING_CONVENTION __stdcall +#else +#define EXPORT_FUNCTION __attribute__((visibility("default"))) +#define CALLING_CONVENTION +#endif + +static const char *lexerName = "simple"; + +extern "C" { + +EXPORT_FUNCTION int CALLING_CONVENTION GetLexerCount() { + return 1; +} + +EXPORT_FUNCTION void CALLING_CONVENTION GetLexerName(unsigned int index, char *name, int buflength) { + *name = 0; + if ((index == 0) && (buflength > static_cast(strlen(lexerName)))) { + strcpy(name, lexerName); + } +} + +EXPORT_FUNCTION LexerFactoryFunction CALLING_CONVENTION GetLexerFactory(unsigned int index) { + if (index == 0) + return LexerSimple::LexerFactorySimple; + else + return 0; +} + +EXPORT_FUNCTION Scintilla::ILexer5* CALLING_CONVENTION CreateLexer(const char *name) { + if (0 == strcmp(name, lexerName)) { + return LexerSimple::LexerFactorySimple(); + } + return nullptr; +} + +EXPORT_FUNCTION const char * CALLING_CONVENTION GetNameSpace() { + return "example"; +} + +} diff --git a/src/lexilla/include/LexicalStyles.iface b/src/lexilla/include/LexicalStyles.iface new file mode 100644 index 000000000..ca9ee547e --- /dev/null +++ b/src/lexilla/include/LexicalStyles.iface @@ -0,0 +1,2330 @@ +## This file defines the interface to Lexilla + +## Copyright 2000-2020 by Neil Hodgson +## The License.txt file describes the conditions under which this software may be distributed. + +## Similar file structure as Scintilla.iface but only contains constants. + +cat Default + +################################################ +# For SciLexer.h +enu Lexer=SCLEX_ +val SCLEX_CONTAINER=0 +val SCLEX_NULL=1 +val SCLEX_PYTHON=2 +val SCLEX_CPP=3 +val SCLEX_HTML=4 +val SCLEX_XML=5 +val SCLEX_PERL=6 +val SCLEX_SQL=7 +val SCLEX_VB=8 +val SCLEX_PROPERTIES=9 +val SCLEX_ERRORLIST=10 +val SCLEX_MAKEFILE=11 +val SCLEX_BATCH=12 +val SCLEX_XCODE=13 +val SCLEX_LATEX=14 +val SCLEX_LUA=15 +val SCLEX_DIFF=16 +val SCLEX_CONF=17 +val SCLEX_PASCAL=18 +val SCLEX_AVE=19 +val SCLEX_ADA=20 +val SCLEX_LISP=21 +val SCLEX_RUBY=22 +val SCLEX_EIFFEL=23 +val SCLEX_EIFFELKW=24 +val SCLEX_TCL=25 +val SCLEX_NNCRONTAB=26 +val SCLEX_BULLANT=27 +val SCLEX_VBSCRIPT=28 +val SCLEX_BAAN=31 +val SCLEX_MATLAB=32 +val SCLEX_SCRIPTOL=33 +val SCLEX_ASM=34 +val SCLEX_CPPNOCASE=35 +val SCLEX_FORTRAN=36 +val SCLEX_F77=37 +val SCLEX_CSS=38 +val SCLEX_POV=39 +val SCLEX_LOUT=40 +val SCLEX_ESCRIPT=41 +val SCLEX_PS=42 +val SCLEX_NSIS=43 +val SCLEX_MMIXAL=44 +val SCLEX_CLW=45 +val SCLEX_CLWNOCASE=46 +val SCLEX_LOT=47 +val SCLEX_YAML=48 +val SCLEX_TEX=49 +val SCLEX_METAPOST=50 +val SCLEX_POWERBASIC=51 +val SCLEX_FORTH=52 +val SCLEX_ERLANG=53 +val SCLEX_OCTAVE=54 +val SCLEX_MSSQL=55 +val SCLEX_VERILOG=56 +val SCLEX_KIX=57 +val SCLEX_GUI4CLI=58 +val SCLEX_SPECMAN=59 +val SCLEX_AU3=60 +val SCLEX_APDL=61 +val SCLEX_BASH=62 +val SCLEX_ASN1=63 +val SCLEX_VHDL=64 +val SCLEX_CAML=65 +val SCLEX_BLITZBASIC=66 +val SCLEX_PUREBASIC=67 +val SCLEX_HASKELL=68 +val SCLEX_PHPSCRIPT=69 +val SCLEX_TADS3=70 +val SCLEX_REBOL=71 +val SCLEX_SMALLTALK=72 +val SCLEX_FLAGSHIP=73 +val SCLEX_CSOUND=74 +val SCLEX_FREEBASIC=75 +val SCLEX_INNOSETUP=76 +val SCLEX_OPAL=77 +val SCLEX_SPICE=78 +val SCLEX_D=79 +val SCLEX_CMAKE=80 +val SCLEX_GAP=81 +val SCLEX_PLM=82 +val SCLEX_PROGRESS=83 +val SCLEX_ABAQUS=84 +val SCLEX_ASYMPTOTE=85 +val SCLEX_R=86 +val SCLEX_MAGIK=87 +val SCLEX_POWERSHELL=88 +val SCLEX_MYSQL=89 +val SCLEX_PO=90 +val SCLEX_TAL=91 +val SCLEX_COBOL=92 +val SCLEX_TACL=93 +val SCLEX_SORCUS=94 +val SCLEX_POWERPRO=95 +val SCLEX_NIMROD=96 +val SCLEX_SML=97 +val SCLEX_MARKDOWN=98 +val SCLEX_TXT2TAGS=99 +val SCLEX_A68K=100 +val SCLEX_MODULA=101 +val SCLEX_COFFEESCRIPT=102 +val SCLEX_TCMD=103 +val SCLEX_AVS=104 +val SCLEX_ECL=105 +val SCLEX_OSCRIPT=106 +val SCLEX_VISUALPROLOG=107 +val SCLEX_LITERATEHASKELL=108 +val SCLEX_STTXT=109 +val SCLEX_KVIRC=110 +val SCLEX_RUST=111 +val SCLEX_DMAP=112 +val SCLEX_AS=113 +val SCLEX_DMIS=114 +val SCLEX_REGISTRY=115 +val SCLEX_BIBTEX=116 +val SCLEX_SREC=117 +val SCLEX_IHEX=118 +val SCLEX_TEHEX=119 +val SCLEX_JSON=120 +val SCLEX_EDIFACT=121 +val SCLEX_INDENT=122 +val SCLEX_MAXIMA=123 +val SCLEX_STATA=124 +val SCLEX_SAS=125 +val SCLEX_NIM=126 +val SCLEX_CIL=127 +val SCLEX_X12=128 +val SCLEX_DATAFLEX=129 +val SCLEX_HOLLYWOOD=130 +val SCLEX_RAKU=131 +val SCLEX_FSHARP=132 +val SCLEX_JULIA=133 +val SCLEX_ASCIIDOC=134 +val SCLEX_GDSCRIPT=135 +val SCLEX_TOML=136 + +# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a +# value assigned in sequence from SCLEX_AUTOMATIC+1. +val SCLEX_AUTOMATIC=1000 +# Lexical states for SCLEX_PYTHON +lex Python=SCLEX_PYTHON SCE_P_ +lex Nimrod=SCLEX_NIMROD SCE_P_ +val SCE_P_DEFAULT=0 +val SCE_P_COMMENTLINE=1 +val SCE_P_NUMBER=2 +val SCE_P_STRING=3 +val SCE_P_CHARACTER=4 +val SCE_P_WORD=5 +val SCE_P_TRIPLE=6 +val SCE_P_TRIPLEDOUBLE=7 +val SCE_P_CLASSNAME=8 +val SCE_P_DEFNAME=9 +val SCE_P_OPERATOR=10 +val SCE_P_IDENTIFIER=11 +val SCE_P_COMMENTBLOCK=12 +val SCE_P_STRINGEOL=13 +val SCE_P_WORD2=14 +val SCE_P_DECORATOR=15 +val SCE_P_FSTRING=16 +val SCE_P_FCHARACTER=17 +val SCE_P_FTRIPLE=18 +val SCE_P_FTRIPLEDOUBLE=19 +val SCE_P_ATTRIBUTE=20 +# Lexical states for SCLEX_CPP +# Lexical states for SCLEX_BULLANT +# Lexical states for SCLEX_COBOL +# Lexical states for SCLEX_TACL +# Lexical states for SCLEX_TAL +lex Cpp=SCLEX_CPP SCE_C_ +lex BullAnt=SCLEX_BULLANT SCE_C_ +lex COBOL=SCLEX_COBOL SCE_C_ +lex TACL=SCLEX_TACL SCE_C_ +lex TAL=SCLEX_TAL SCE_C_ +val SCE_C_DEFAULT=0 +val SCE_C_COMMENT=1 +val SCE_C_COMMENTLINE=2 +val SCE_C_COMMENTDOC=3 +val SCE_C_NUMBER=4 +val SCE_C_WORD=5 +val SCE_C_STRING=6 +val SCE_C_CHARACTER=7 +val SCE_C_UUID=8 +val SCE_C_PREPROCESSOR=9 +val SCE_C_OPERATOR=10 +val SCE_C_IDENTIFIER=11 +val SCE_C_STRINGEOL=12 +val SCE_C_VERBATIM=13 +val SCE_C_REGEX=14 +val SCE_C_COMMENTLINEDOC=15 +val SCE_C_WORD2=16 +val SCE_C_COMMENTDOCKEYWORD=17 +val SCE_C_COMMENTDOCKEYWORDERROR=18 +val SCE_C_GLOBALCLASS=19 +val SCE_C_STRINGRAW=20 +val SCE_C_TRIPLEVERBATIM=21 +val SCE_C_HASHQUOTEDSTRING=22 +val SCE_C_PREPROCESSORCOMMENT=23 +val SCE_C_PREPROCESSORCOMMENTDOC=24 +val SCE_C_USERLITERAL=25 +val SCE_C_TASKMARKER=26 +val SCE_C_ESCAPESEQUENCE=27 +# Lexical states for SCLEX_D +lex D=SCLEX_D SCE_D_ +val SCE_D_DEFAULT=0 +val SCE_D_COMMENT=1 +val SCE_D_COMMENTLINE=2 +val SCE_D_COMMENTDOC=3 +val SCE_D_COMMENTNESTED=4 +val SCE_D_NUMBER=5 +val SCE_D_WORD=6 +val SCE_D_WORD2=7 +val SCE_D_WORD3=8 +val SCE_D_TYPEDEF=9 +val SCE_D_STRING=10 +val SCE_D_STRINGEOL=11 +val SCE_D_CHARACTER=12 +val SCE_D_OPERATOR=13 +val SCE_D_IDENTIFIER=14 +val SCE_D_COMMENTLINEDOC=15 +val SCE_D_COMMENTDOCKEYWORD=16 +val SCE_D_COMMENTDOCKEYWORDERROR=17 +val SCE_D_STRINGB=18 +val SCE_D_STRINGR=19 +val SCE_D_WORD5=20 +val SCE_D_WORD6=21 +val SCE_D_WORD7=22 +# Lexical states for SCLEX_TCL +lex TCL=SCLEX_TCL SCE_TCL_ +val SCE_TCL_DEFAULT=0 +val SCE_TCL_COMMENT=1 +val SCE_TCL_COMMENTLINE=2 +val SCE_TCL_NUMBER=3 +val SCE_TCL_WORD_IN_QUOTE=4 +val SCE_TCL_IN_QUOTE=5 +val SCE_TCL_OPERATOR=6 +val SCE_TCL_IDENTIFIER=7 +val SCE_TCL_SUBSTITUTION=8 +val SCE_TCL_SUB_BRACE=9 +val SCE_TCL_MODIFIER=10 +val SCE_TCL_EXPAND=11 +val SCE_TCL_WORD=12 +val SCE_TCL_WORD2=13 +val SCE_TCL_WORD3=14 +val SCE_TCL_WORD4=15 +val SCE_TCL_WORD5=16 +val SCE_TCL_WORD6=17 +val SCE_TCL_WORD7=18 +val SCE_TCL_WORD8=19 +val SCE_TCL_COMMENT_BOX=20 +val SCE_TCL_BLOCK_COMMENT=21 +# Lexical states for SCLEX_HTML, SCLEX_XML +lex HTML=SCLEX_HTML SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_ +lex XML=SCLEX_XML SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_ +val SCE_H_DEFAULT=0 +val SCE_H_TAG=1 +val SCE_H_TAGUNKNOWN=2 +val SCE_H_ATTRIBUTE=3 +val SCE_H_ATTRIBUTEUNKNOWN=4 +val SCE_H_NUMBER=5 +val SCE_H_DOUBLESTRING=6 +val SCE_H_SINGLESTRING=7 +val SCE_H_OTHER=8 +val SCE_H_COMMENT=9 +val SCE_H_ENTITY=10 +# XML and ASP +val SCE_H_TAGEND=11 +val SCE_H_XMLSTART=12 +val SCE_H_XMLEND=13 +val SCE_H_SCRIPT=14 +val SCE_H_ASP=15 +val SCE_H_ASPAT=16 +val SCE_H_CDATA=17 +val SCE_H_QUESTION=18 +# More HTML +val SCE_H_VALUE=19 +# X-Code, ASP.NET, JSP +val SCE_H_XCCOMMENT=20 +# SGML +val SCE_H_SGML_DEFAULT=21 +val SCE_H_SGML_COMMAND=22 +val SCE_H_SGML_1ST_PARAM=23 +val SCE_H_SGML_DOUBLESTRING=24 +val SCE_H_SGML_SIMPLESTRING=25 +val SCE_H_SGML_ERROR=26 +val SCE_H_SGML_SPECIAL=27 +val SCE_H_SGML_ENTITY=28 +val SCE_H_SGML_COMMENT=29 +val SCE_H_SGML_1ST_PARAM_COMMENT=30 +val SCE_H_SGML_BLOCK_DEFAULT=31 +# Embedded Javascript +val SCE_HJ_START=40 +val SCE_HJ_DEFAULT=41 +val SCE_HJ_COMMENT=42 +val SCE_HJ_COMMENTLINE=43 +val SCE_HJ_COMMENTDOC=44 +val SCE_HJ_NUMBER=45 +val SCE_HJ_WORD=46 +val SCE_HJ_KEYWORD=47 +val SCE_HJ_DOUBLESTRING=48 +val SCE_HJ_SINGLESTRING=49 +val SCE_HJ_SYMBOLS=50 +val SCE_HJ_STRINGEOL=51 +val SCE_HJ_REGEX=52 +# ASP Javascript +val SCE_HJA_START=55 +val SCE_HJA_DEFAULT=56 +val SCE_HJA_COMMENT=57 +val SCE_HJA_COMMENTLINE=58 +val SCE_HJA_COMMENTDOC=59 +val SCE_HJA_NUMBER=60 +val SCE_HJA_WORD=61 +val SCE_HJA_KEYWORD=62 +val SCE_HJA_DOUBLESTRING=63 +val SCE_HJA_SINGLESTRING=64 +val SCE_HJA_SYMBOLS=65 +val SCE_HJA_STRINGEOL=66 +val SCE_HJA_REGEX=67 +# Embedded VBScript +val SCE_HB_START=70 +val SCE_HB_DEFAULT=71 +val SCE_HB_COMMENTLINE=72 +val SCE_HB_NUMBER=73 +val SCE_HB_WORD=74 +val SCE_HB_STRING=75 +val SCE_HB_IDENTIFIER=76 +val SCE_HB_STRINGEOL=77 +# ASP VBScript +val SCE_HBA_START=80 +val SCE_HBA_DEFAULT=81 +val SCE_HBA_COMMENTLINE=82 +val SCE_HBA_NUMBER=83 +val SCE_HBA_WORD=84 +val SCE_HBA_STRING=85 +val SCE_HBA_IDENTIFIER=86 +val SCE_HBA_STRINGEOL=87 +# Embedded Python +val SCE_HP_START=90 +val SCE_HP_DEFAULT=91 +val SCE_HP_COMMENTLINE=92 +val SCE_HP_NUMBER=93 +val SCE_HP_STRING=94 +val SCE_HP_CHARACTER=95 +val SCE_HP_WORD=96 +val SCE_HP_TRIPLE=97 +val SCE_HP_TRIPLEDOUBLE=98 +val SCE_HP_CLASSNAME=99 +val SCE_HP_DEFNAME=100 +val SCE_HP_OPERATOR=101 +val SCE_HP_IDENTIFIER=102 +# PHP +val SCE_HPHP_COMPLEX_VARIABLE=104 +# ASP Python +val SCE_HPA_START=105 +val SCE_HPA_DEFAULT=106 +val SCE_HPA_COMMENTLINE=107 +val SCE_HPA_NUMBER=108 +val SCE_HPA_STRING=109 +val SCE_HPA_CHARACTER=110 +val SCE_HPA_WORD=111 +val SCE_HPA_TRIPLE=112 +val SCE_HPA_TRIPLEDOUBLE=113 +val SCE_HPA_CLASSNAME=114 +val SCE_HPA_DEFNAME=115 +val SCE_HPA_OPERATOR=116 +val SCE_HPA_IDENTIFIER=117 +# PHP +val SCE_HPHP_DEFAULT=118 +val SCE_HPHP_HSTRING=119 +val SCE_HPHP_SIMPLESTRING=120 +val SCE_HPHP_WORD=121 +val SCE_HPHP_NUMBER=122 +val SCE_HPHP_VARIABLE=123 +val SCE_HPHP_COMMENT=124 +val SCE_HPHP_COMMENTLINE=125 +val SCE_HPHP_HSTRING_VARIABLE=126 +val SCE_HPHP_OPERATOR=127 +# Lexical states for SCLEX_PERL +lex Perl=SCLEX_PERL SCE_PL_ +val SCE_PL_DEFAULT=0 +val SCE_PL_ERROR=1 +val SCE_PL_COMMENTLINE=2 +val SCE_PL_POD=3 +val SCE_PL_NUMBER=4 +val SCE_PL_WORD=5 +val SCE_PL_STRING=6 +val SCE_PL_CHARACTER=7 +val SCE_PL_PUNCTUATION=8 +val SCE_PL_PREPROCESSOR=9 +val SCE_PL_OPERATOR=10 +val SCE_PL_IDENTIFIER=11 +val SCE_PL_SCALAR=12 +val SCE_PL_ARRAY=13 +val SCE_PL_HASH=14 +val SCE_PL_SYMBOLTABLE=15 +val SCE_PL_VARIABLE_INDEXER=16 +val SCE_PL_REGEX=17 +val SCE_PL_REGSUBST=18 +val SCE_PL_LONGQUOTE=19 +val SCE_PL_BACKTICKS=20 +val SCE_PL_DATASECTION=21 +val SCE_PL_HERE_DELIM=22 +val SCE_PL_HERE_Q=23 +val SCE_PL_HERE_QQ=24 +val SCE_PL_HERE_QX=25 +val SCE_PL_STRING_Q=26 +val SCE_PL_STRING_QQ=27 +val SCE_PL_STRING_QX=28 +val SCE_PL_STRING_QR=29 +val SCE_PL_STRING_QW=30 +val SCE_PL_POD_VERB=31 +val SCE_PL_SUB_PROTOTYPE=40 +val SCE_PL_FORMAT_IDENT=41 +val SCE_PL_FORMAT=42 +val SCE_PL_STRING_VAR=43 +val SCE_PL_XLAT=44 +val SCE_PL_REGEX_VAR=54 +val SCE_PL_REGSUBST_VAR=55 +val SCE_PL_BACKTICKS_VAR=57 +val SCE_PL_HERE_QQ_VAR=61 +val SCE_PL_HERE_QX_VAR=62 +val SCE_PL_STRING_QQ_VAR=64 +val SCE_PL_STRING_QX_VAR=65 +val SCE_PL_STRING_QR_VAR=66 +# Lexical states for SCLEX_RUBY +lex Ruby=SCLEX_RUBY SCE_RB_ +val SCE_RB_DEFAULT=0 +val SCE_RB_ERROR=1 +val SCE_RB_COMMENTLINE=2 +val SCE_RB_POD=3 +val SCE_RB_NUMBER=4 +val SCE_RB_WORD=5 +val SCE_RB_STRING=6 +val SCE_RB_CHARACTER=7 +val SCE_RB_CLASSNAME=8 +val SCE_RB_DEFNAME=9 +val SCE_RB_OPERATOR=10 +val SCE_RB_IDENTIFIER=11 +val SCE_RB_REGEX=12 +val SCE_RB_GLOBAL=13 +val SCE_RB_SYMBOL=14 +val SCE_RB_MODULE_NAME=15 +val SCE_RB_INSTANCE_VAR=16 +val SCE_RB_CLASS_VAR=17 +val SCE_RB_BACKTICKS=18 +val SCE_RB_DATASECTION=19 +val SCE_RB_HERE_DELIM=20 +val SCE_RB_HERE_Q=21 +val SCE_RB_HERE_QQ=22 +val SCE_RB_HERE_QX=23 +val SCE_RB_STRING_Q=24 +val SCE_RB_STRING_QQ=25 +val SCE_RB_STRING_QX=26 +val SCE_RB_STRING_QR=27 +val SCE_RB_STRING_QW=28 +val SCE_RB_WORD_DEMOTED=29 +val SCE_RB_STDIN=30 +val SCE_RB_STDOUT=31 +val SCE_RB_STDERR=40 +val SCE_RB_STRING_W=41 +val SCE_RB_STRING_I=42 +val SCE_RB_STRING_QI=43 +val SCE_RB_STRING_QS=44 +val SCE_RB_UPPER_BOUND=45 +# Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC, SCLEX_BLITZBASIC, SCLEX_PUREBASIC, SCLEX_FREEBASIC +lex VB=SCLEX_VB SCE_B_ +lex VBScript=SCLEX_VBSCRIPT SCE_B_ +lex PowerBasic=SCLEX_POWERBASIC SCE_B_ +lex BlitzBasic=SCLEX_BLITZBASIC SCE_B_ +lex PureBasic=SCLEX_PUREBASIC SCE_B_ +lex FreeBasic=SCLEX_FREEBASIC SCE_B_ +val SCE_B_DEFAULT=0 +val SCE_B_COMMENT=1 +val SCE_B_NUMBER=2 +val SCE_B_KEYWORD=3 +val SCE_B_STRING=4 +val SCE_B_PREPROCESSOR=5 +val SCE_B_OPERATOR=6 +val SCE_B_IDENTIFIER=7 +val SCE_B_DATE=8 +val SCE_B_STRINGEOL=9 +val SCE_B_KEYWORD2=10 +val SCE_B_KEYWORD3=11 +val SCE_B_KEYWORD4=12 +val SCE_B_CONSTANT=13 +val SCE_B_ASM=14 +val SCE_B_LABEL=15 +val SCE_B_ERROR=16 +val SCE_B_HEXNUMBER=17 +val SCE_B_BINNUMBER=18 +val SCE_B_COMMENTBLOCK=19 +val SCE_B_DOCLINE=20 +val SCE_B_DOCBLOCK=21 +val SCE_B_DOCKEYWORD=22 +# Lexical states for SCLEX_PROPERTIES +lex Properties=SCLEX_PROPERTIES SCE_PROPS_ +val SCE_PROPS_DEFAULT=0 +val SCE_PROPS_COMMENT=1 +val SCE_PROPS_SECTION=2 +val SCE_PROPS_ASSIGNMENT=3 +val SCE_PROPS_DEFVAL=4 +val SCE_PROPS_KEY=5 +# Lexical states for SCLEX_LATEX +lex LaTeX=SCLEX_LATEX SCE_L_ +val SCE_L_DEFAULT=0 +val SCE_L_COMMAND=1 +val SCE_L_TAG=2 +val SCE_L_MATH=3 +val SCE_L_COMMENT=4 +val SCE_L_TAG2=5 +val SCE_L_MATH2=6 +val SCE_L_COMMENT2=7 +val SCE_L_VERBATIM=8 +val SCE_L_SHORTCMD=9 +val SCE_L_SPECIAL=10 +val SCE_L_CMDOPT=11 +val SCE_L_ERROR=12 +# Lexical states for SCLEX_LUA +lex Lua=SCLEX_LUA SCE_LUA_ +val SCE_LUA_DEFAULT=0 +val SCE_LUA_COMMENT=1 +val SCE_LUA_COMMENTLINE=2 +val SCE_LUA_COMMENTDOC=3 +val SCE_LUA_NUMBER=4 +val SCE_LUA_WORD=5 +val SCE_LUA_STRING=6 +val SCE_LUA_CHARACTER=7 +val SCE_LUA_LITERALSTRING=8 +val SCE_LUA_PREPROCESSOR=9 +val SCE_LUA_OPERATOR=10 +val SCE_LUA_IDENTIFIER=11 +val SCE_LUA_STRINGEOL=12 +val SCE_LUA_WORD2=13 +val SCE_LUA_WORD3=14 +val SCE_LUA_WORD4=15 +val SCE_LUA_WORD5=16 +val SCE_LUA_WORD6=17 +val SCE_LUA_WORD7=18 +val SCE_LUA_WORD8=19 +val SCE_LUA_LABEL=20 +# Lexical states for SCLEX_ERRORLIST +lex ErrorList=SCLEX_ERRORLIST SCE_ERR_ +val SCE_ERR_DEFAULT=0 +val SCE_ERR_PYTHON=1 +val SCE_ERR_GCC=2 +val SCE_ERR_MS=3 +val SCE_ERR_CMD=4 +val SCE_ERR_BORLAND=5 +val SCE_ERR_PERL=6 +val SCE_ERR_NET=7 +val SCE_ERR_LUA=8 +val SCE_ERR_CTAG=9 +val SCE_ERR_DIFF_CHANGED=10 +val SCE_ERR_DIFF_ADDITION=11 +val SCE_ERR_DIFF_DELETION=12 +val SCE_ERR_DIFF_MESSAGE=13 +val SCE_ERR_PHP=14 +val SCE_ERR_ELF=15 +val SCE_ERR_IFC=16 +val SCE_ERR_IFORT=17 +val SCE_ERR_ABSF=18 +val SCE_ERR_TIDY=19 +val SCE_ERR_JAVA_STACK=20 +val SCE_ERR_VALUE=21 +val SCE_ERR_GCC_INCLUDED_FROM=22 +val SCE_ERR_ESCSEQ=23 +val SCE_ERR_ESCSEQ_UNKNOWN=24 +val SCE_ERR_GCC_EXCERPT=25 +val SCE_ERR_BASH=26 +val SCE_ERR_ES_BLACK=40 +val SCE_ERR_ES_RED=41 +val SCE_ERR_ES_GREEN=42 +val SCE_ERR_ES_BROWN=43 +val SCE_ERR_ES_BLUE=44 +val SCE_ERR_ES_MAGENTA=45 +val SCE_ERR_ES_CYAN=46 +val SCE_ERR_ES_GRAY=47 +val SCE_ERR_ES_DARK_GRAY=48 +val SCE_ERR_ES_BRIGHT_RED=49 +val SCE_ERR_ES_BRIGHT_GREEN=50 +val SCE_ERR_ES_YELLOW=51 +val SCE_ERR_ES_BRIGHT_BLUE=52 +val SCE_ERR_ES_BRIGHT_MAGENTA=53 +val SCE_ERR_ES_BRIGHT_CYAN=54 +val SCE_ERR_ES_WHITE=55 +# Lexical states for SCLEX_BATCH +lex Batch=SCLEX_BATCH SCE_BAT_ +val SCE_BAT_DEFAULT=0 +val SCE_BAT_COMMENT=1 +val SCE_BAT_WORD=2 +val SCE_BAT_LABEL=3 +val SCE_BAT_HIDE=4 +val SCE_BAT_COMMAND=5 +val SCE_BAT_IDENTIFIER=6 +val SCE_BAT_OPERATOR=7 +val SCE_BAT_AFTER_LABEL=8 +# Lexical states for SCLEX_TCMD +lex TCMD=SCLEX_TCMD SCE_TCMD_ +val SCE_TCMD_DEFAULT=0 +val SCE_TCMD_COMMENT=1 +val SCE_TCMD_WORD=2 +val SCE_TCMD_LABEL=3 +val SCE_TCMD_HIDE=4 +val SCE_TCMD_COMMAND=5 +val SCE_TCMD_IDENTIFIER=6 +val SCE_TCMD_OPERATOR=7 +val SCE_TCMD_ENVIRONMENT=8 +val SCE_TCMD_EXPANSION=9 +val SCE_TCMD_CLABEL=10 +# Lexical states for SCLEX_MAKEFILE +lex MakeFile=SCLEX_MAKEFILE SCE_MAKE_ +val SCE_MAKE_DEFAULT=0 +val SCE_MAKE_COMMENT=1 +val SCE_MAKE_PREPROCESSOR=2 +val SCE_MAKE_IDENTIFIER=3 +val SCE_MAKE_OPERATOR=4 +val SCE_MAKE_TARGET=5 +val SCE_MAKE_IDEOL=9 +# Lexical states for SCLEX_DIFF +lex Diff=SCLEX_DIFF SCE_DIFF_ +val SCE_DIFF_DEFAULT=0 +val SCE_DIFF_COMMENT=1 +val SCE_DIFF_COMMAND=2 +val SCE_DIFF_HEADER=3 +val SCE_DIFF_POSITION=4 +val SCE_DIFF_DELETED=5 +val SCE_DIFF_ADDED=6 +val SCE_DIFF_CHANGED=7 +val SCE_DIFF_PATCH_ADD=8 +val SCE_DIFF_PATCH_DELETE=9 +val SCE_DIFF_REMOVED_PATCH_ADD=10 +val SCE_DIFF_REMOVED_PATCH_DELETE=11 +# Lexical states for SCLEX_CONF (Apache Configuration Files Lexer) +lex Conf=SCLEX_CONF SCE_CONF_ +val SCE_CONF_DEFAULT=0 +val SCE_CONF_COMMENT=1 +val SCE_CONF_NUMBER=2 +val SCE_CONF_IDENTIFIER=3 +val SCE_CONF_EXTENSION=4 +val SCE_CONF_PARAMETER=5 +val SCE_CONF_STRING=6 +val SCE_CONF_OPERATOR=7 +val SCE_CONF_IP=8 +val SCE_CONF_DIRECTIVE=9 +# Lexical states for SCLEX_AVE, Avenue +lex Avenue=SCLEX_AVE SCE_AVE_ +val SCE_AVE_DEFAULT=0 +val SCE_AVE_COMMENT=1 +val SCE_AVE_NUMBER=2 +val SCE_AVE_WORD=3 +val SCE_AVE_STRING=6 +val SCE_AVE_ENUM=7 +val SCE_AVE_STRINGEOL=8 +val SCE_AVE_IDENTIFIER=9 +val SCE_AVE_OPERATOR=10 +val SCE_AVE_WORD1=11 +val SCE_AVE_WORD2=12 +val SCE_AVE_WORD3=13 +val SCE_AVE_WORD4=14 +val SCE_AVE_WORD5=15 +val SCE_AVE_WORD6=16 +# Lexical states for SCLEX_ADA +lex Ada=SCLEX_ADA SCE_ADA_ +val SCE_ADA_DEFAULT=0 +val SCE_ADA_WORD=1 +val SCE_ADA_IDENTIFIER=2 +val SCE_ADA_NUMBER=3 +val SCE_ADA_DELIMITER=4 +val SCE_ADA_CHARACTER=5 +val SCE_ADA_CHARACTEREOL=6 +val SCE_ADA_STRING=7 +val SCE_ADA_STRINGEOL=8 +val SCE_ADA_LABEL=9 +val SCE_ADA_COMMENTLINE=10 +val SCE_ADA_ILLEGAL=11 +# Lexical states for SCLEX_BAAN +lex Baan=SCLEX_BAAN SCE_BAAN_ +val SCE_BAAN_DEFAULT=0 +val SCE_BAAN_COMMENT=1 +val SCE_BAAN_COMMENTDOC=2 +val SCE_BAAN_NUMBER=3 +val SCE_BAAN_WORD=4 +val SCE_BAAN_STRING=5 +val SCE_BAAN_PREPROCESSOR=6 +val SCE_BAAN_OPERATOR=7 +val SCE_BAAN_IDENTIFIER=8 +val SCE_BAAN_STRINGEOL=9 +val SCE_BAAN_WORD2=10 +val SCE_BAAN_WORD3=11 +val SCE_BAAN_WORD4=12 +val SCE_BAAN_WORD5=13 +val SCE_BAAN_WORD6=14 +val SCE_BAAN_WORD7=15 +val SCE_BAAN_WORD8=16 +val SCE_BAAN_WORD9=17 +val SCE_BAAN_TABLEDEF=18 +val SCE_BAAN_TABLESQL=19 +val SCE_BAAN_FUNCTION=20 +val SCE_BAAN_DOMDEF=21 +val SCE_BAAN_FUNCDEF=22 +val SCE_BAAN_OBJECTDEF=23 +val SCE_BAAN_DEFINEDEF=24 +# Lexical states for SCLEX_LISP +lex Lisp=SCLEX_LISP SCE_LISP_ +val SCE_LISP_DEFAULT=0 +val SCE_LISP_COMMENT=1 +val SCE_LISP_NUMBER=2 +val SCE_LISP_KEYWORD=3 +val SCE_LISP_KEYWORD_KW=4 +val SCE_LISP_SYMBOL=5 +val SCE_LISP_STRING=6 +val SCE_LISP_STRINGEOL=8 +val SCE_LISP_IDENTIFIER=9 +val SCE_LISP_OPERATOR=10 +val SCE_LISP_SPECIAL=11 +val SCE_LISP_MULTI_COMMENT=12 +# Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW +lex Eiffel=SCLEX_EIFFEL SCE_EIFFEL_ +lex EiffelKW=SCLEX_EIFFELKW SCE_EIFFEL_ +val SCE_EIFFEL_DEFAULT=0 +val SCE_EIFFEL_COMMENTLINE=1 +val SCE_EIFFEL_NUMBER=2 +val SCE_EIFFEL_WORD=3 +val SCE_EIFFEL_STRING=4 +val SCE_EIFFEL_CHARACTER=5 +val SCE_EIFFEL_OPERATOR=6 +val SCE_EIFFEL_IDENTIFIER=7 +val SCE_EIFFEL_STRINGEOL=8 +# Lexical states for SCLEX_NNCRONTAB (nnCron crontab Lexer) +lex NNCronTab=SCLEX_NNCRONTAB SCE_NNCRONTAB_ +val SCE_NNCRONTAB_DEFAULT=0 +val SCE_NNCRONTAB_COMMENT=1 +val SCE_NNCRONTAB_TASK=2 +val SCE_NNCRONTAB_SECTION=3 +val SCE_NNCRONTAB_KEYWORD=4 +val SCE_NNCRONTAB_MODIFIER=5 +val SCE_NNCRONTAB_ASTERISK=6 +val SCE_NNCRONTAB_NUMBER=7 +val SCE_NNCRONTAB_STRING=8 +val SCE_NNCRONTAB_ENVIRONMENT=9 +val SCE_NNCRONTAB_IDENTIFIER=10 +# Lexical states for SCLEX_FORTH (Forth Lexer) +lex Forth=SCLEX_FORTH SCE_FORTH_ +val SCE_FORTH_DEFAULT=0 +val SCE_FORTH_COMMENT=1 +val SCE_FORTH_COMMENT_ML=2 +val SCE_FORTH_IDENTIFIER=3 +val SCE_FORTH_CONTROL=4 +val SCE_FORTH_KEYWORD=5 +val SCE_FORTH_DEFWORD=6 +val SCE_FORTH_PREWORD1=7 +val SCE_FORTH_PREWORD2=8 +val SCE_FORTH_NUMBER=9 +val SCE_FORTH_STRING=10 +val SCE_FORTH_LOCALE=11 +# Lexical states for SCLEX_MATLAB +lex MatLab=SCLEX_MATLAB SCE_MATLAB_ +val SCE_MATLAB_DEFAULT=0 +val SCE_MATLAB_COMMENT=1 +val SCE_MATLAB_COMMAND=2 +val SCE_MATLAB_NUMBER=3 +val SCE_MATLAB_KEYWORD=4 +# single quoted string +val SCE_MATLAB_STRING=5 +val SCE_MATLAB_OPERATOR=6 +val SCE_MATLAB_IDENTIFIER=7 +val SCE_MATLAB_DOUBLEQUOTESTRING=8 +# Lexical states for SCLEX_MAXIMA +lex Maxima=SCLEX_MAXIMA SCE_MAXIMA_ +val SCE_MAXIMA_OPERATOR=0 +val SCE_MAXIMA_COMMANDENDING=1 +val SCE_MAXIMA_COMMENT=2 +val SCE_MAXIMA_NUMBER=3 +val SCE_MAXIMA_STRING=4 +val SCE_MAXIMA_COMMAND=5 +val SCE_MAXIMA_VARIABLE=6 +val SCE_MAXIMA_UNKNOWN=7 +# Lexical states for SCLEX_SCRIPTOL +lex Sol=SCLEX_SCRIPTOL SCE_SCRIPTOL_ +val SCE_SCRIPTOL_DEFAULT=0 +val SCE_SCRIPTOL_WHITE=1 +val SCE_SCRIPTOL_COMMENTLINE=2 +val SCE_SCRIPTOL_PERSISTENT=3 +val SCE_SCRIPTOL_CSTYLE=4 +val SCE_SCRIPTOL_COMMENTBLOCK=5 +val SCE_SCRIPTOL_NUMBER=6 +val SCE_SCRIPTOL_STRING=7 +val SCE_SCRIPTOL_CHARACTER=8 +val SCE_SCRIPTOL_STRINGEOL=9 +val SCE_SCRIPTOL_KEYWORD=10 +val SCE_SCRIPTOL_OPERATOR=11 +val SCE_SCRIPTOL_IDENTIFIER=12 +val SCE_SCRIPTOL_TRIPLE=13 +val SCE_SCRIPTOL_CLASSNAME=14 +val SCE_SCRIPTOL_PREPROCESSOR=15 +# Lexical states for SCLEX_ASM, SCLEX_AS +lex Asm=SCLEX_ASM SCE_ASM_ +lex As=SCLEX_AS SCE_ASM_ +val SCE_ASM_DEFAULT=0 +val SCE_ASM_COMMENT=1 +val SCE_ASM_NUMBER=2 +val SCE_ASM_STRING=3 +val SCE_ASM_OPERATOR=4 +val SCE_ASM_IDENTIFIER=5 +val SCE_ASM_CPUINSTRUCTION=6 +val SCE_ASM_MATHINSTRUCTION=7 +val SCE_ASM_REGISTER=8 +val SCE_ASM_DIRECTIVE=9 +val SCE_ASM_DIRECTIVEOPERAND=10 +val SCE_ASM_COMMENTBLOCK=11 +val SCE_ASM_CHARACTER=12 +val SCE_ASM_STRINGEOL=13 +val SCE_ASM_EXTINSTRUCTION=14 +val SCE_ASM_COMMENTDIRECTIVE=15 +# Lexical states for SCLEX_FORTRAN +lex Fortran=SCLEX_FORTRAN SCE_F_ +lex F77=SCLEX_F77 SCE_F_ +val SCE_F_DEFAULT=0 +val SCE_F_COMMENT=1 +val SCE_F_NUMBER=2 +val SCE_F_STRING1=3 +val SCE_F_STRING2=4 +val SCE_F_STRINGEOL=5 +val SCE_F_OPERATOR=6 +val SCE_F_IDENTIFIER=7 +val SCE_F_WORD=8 +val SCE_F_WORD2=9 +val SCE_F_WORD3=10 +val SCE_F_PREPROCESSOR=11 +val SCE_F_OPERATOR2=12 +val SCE_F_LABEL=13 +val SCE_F_CONTINUATION=14 +# Lexical states for SCLEX_CSS +lex CSS=SCLEX_CSS SCE_CSS_ +val SCE_CSS_DEFAULT=0 +val SCE_CSS_TAG=1 +val SCE_CSS_CLASS=2 +val SCE_CSS_PSEUDOCLASS=3 +val SCE_CSS_UNKNOWN_PSEUDOCLASS=4 +val SCE_CSS_OPERATOR=5 +val SCE_CSS_IDENTIFIER=6 +val SCE_CSS_UNKNOWN_IDENTIFIER=7 +val SCE_CSS_VALUE=8 +val SCE_CSS_COMMENT=9 +val SCE_CSS_ID=10 +val SCE_CSS_IMPORTANT=11 +val SCE_CSS_DIRECTIVE=12 +val SCE_CSS_DOUBLESTRING=13 +val SCE_CSS_SINGLESTRING=14 +val SCE_CSS_IDENTIFIER2=15 +val SCE_CSS_ATTRIBUTE=16 +val SCE_CSS_IDENTIFIER3=17 +val SCE_CSS_PSEUDOELEMENT=18 +val SCE_CSS_EXTENDED_IDENTIFIER=19 +val SCE_CSS_EXTENDED_PSEUDOCLASS=20 +val SCE_CSS_EXTENDED_PSEUDOELEMENT=21 +val SCE_CSS_GROUP_RULE=22 +val SCE_CSS_VARIABLE=23 +# Lexical states for SCLEX_POV +lex POV=SCLEX_POV SCE_POV_ +val SCE_POV_DEFAULT=0 +val SCE_POV_COMMENT=1 +val SCE_POV_COMMENTLINE=2 +val SCE_POV_NUMBER=3 +val SCE_POV_OPERATOR=4 +val SCE_POV_IDENTIFIER=5 +val SCE_POV_STRING=6 +val SCE_POV_STRINGEOL=7 +val SCE_POV_DIRECTIVE=8 +val SCE_POV_BADDIRECTIVE=9 +val SCE_POV_WORD2=10 +val SCE_POV_WORD3=11 +val SCE_POV_WORD4=12 +val SCE_POV_WORD5=13 +val SCE_POV_WORD6=14 +val SCE_POV_WORD7=15 +val SCE_POV_WORD8=16 +# Lexical states for SCLEX_LOUT +lex LOUT=SCLEX_LOUT SCE_LOUT_ +val SCE_LOUT_DEFAULT=0 +val SCE_LOUT_COMMENT=1 +val SCE_LOUT_NUMBER=2 +val SCE_LOUT_WORD=3 +val SCE_LOUT_WORD2=4 +val SCE_LOUT_WORD3=5 +val SCE_LOUT_WORD4=6 +val SCE_LOUT_STRING=7 +val SCE_LOUT_OPERATOR=8 +val SCE_LOUT_IDENTIFIER=9 +val SCE_LOUT_STRINGEOL=10 +# Lexical states for SCLEX_ESCRIPT +lex ESCRIPT=SCLEX_ESCRIPT SCE_ESCRIPT_ +val SCE_ESCRIPT_DEFAULT=0 +val SCE_ESCRIPT_COMMENT=1 +val SCE_ESCRIPT_COMMENTLINE=2 +val SCE_ESCRIPT_COMMENTDOC=3 +val SCE_ESCRIPT_NUMBER=4 +val SCE_ESCRIPT_WORD=5 +val SCE_ESCRIPT_STRING=6 +val SCE_ESCRIPT_OPERATOR=7 +val SCE_ESCRIPT_IDENTIFIER=8 +val SCE_ESCRIPT_BRACE=9 +val SCE_ESCRIPT_WORD2=10 +val SCE_ESCRIPT_WORD3=11 +# Lexical states for SCLEX_PS +lex PS=SCLEX_PS SCE_PS_ +val SCE_PS_DEFAULT=0 +val SCE_PS_COMMENT=1 +val SCE_PS_DSC_COMMENT=2 +val SCE_PS_DSC_VALUE=3 +val SCE_PS_NUMBER=4 +val SCE_PS_NAME=5 +val SCE_PS_KEYWORD=6 +val SCE_PS_LITERAL=7 +val SCE_PS_IMMEVAL=8 +val SCE_PS_PAREN_ARRAY=9 +val SCE_PS_PAREN_DICT=10 +val SCE_PS_PAREN_PROC=11 +val SCE_PS_TEXT=12 +val SCE_PS_HEXSTRING=13 +val SCE_PS_BASE85STRING=14 +val SCE_PS_BADSTRINGCHAR=15 +# Lexical states for SCLEX_NSIS +lex NSIS=SCLEX_NSIS SCE_NSIS_ +val SCE_NSIS_DEFAULT=0 +val SCE_NSIS_COMMENT=1 +val SCE_NSIS_STRINGDQ=2 +val SCE_NSIS_STRINGLQ=3 +val SCE_NSIS_STRINGRQ=4 +val SCE_NSIS_FUNCTION=5 +val SCE_NSIS_VARIABLE=6 +val SCE_NSIS_LABEL=7 +val SCE_NSIS_USERDEFINED=8 +val SCE_NSIS_SECTIONDEF=9 +val SCE_NSIS_SUBSECTIONDEF=10 +val SCE_NSIS_IFDEFINEDEF=11 +val SCE_NSIS_MACRODEF=12 +val SCE_NSIS_STRINGVAR=13 +val SCE_NSIS_NUMBER=14 +val SCE_NSIS_SECTIONGROUP=15 +val SCE_NSIS_PAGEEX=16 +val SCE_NSIS_FUNCTIONDEF=17 +val SCE_NSIS_COMMENTBOX=18 +# Lexical states for SCLEX_MMIXAL +lex MMIXAL=SCLEX_MMIXAL SCE_MMIXAL_ +val SCE_MMIXAL_LEADWS=0 +val SCE_MMIXAL_COMMENT=1 +val SCE_MMIXAL_LABEL=2 +val SCE_MMIXAL_OPCODE=3 +val SCE_MMIXAL_OPCODE_PRE=4 +val SCE_MMIXAL_OPCODE_VALID=5 +val SCE_MMIXAL_OPCODE_UNKNOWN=6 +val SCE_MMIXAL_OPCODE_POST=7 +val SCE_MMIXAL_OPERANDS=8 +val SCE_MMIXAL_NUMBER=9 +val SCE_MMIXAL_REF=10 +val SCE_MMIXAL_CHAR=11 +val SCE_MMIXAL_STRING=12 +val SCE_MMIXAL_REGISTER=13 +val SCE_MMIXAL_HEX=14 +val SCE_MMIXAL_OPERATOR=15 +val SCE_MMIXAL_SYMBOL=16 +val SCE_MMIXAL_INCLUDE=17 +# Lexical states for SCLEX_CLW +lex Clarion=SCLEX_CLW SCE_CLW_ +val SCE_CLW_DEFAULT=0 +val SCE_CLW_LABEL=1 +val SCE_CLW_COMMENT=2 +val SCE_CLW_STRING=3 +val SCE_CLW_USER_IDENTIFIER=4 +val SCE_CLW_INTEGER_CONSTANT=5 +val SCE_CLW_REAL_CONSTANT=6 +val SCE_CLW_PICTURE_STRING=7 +val SCE_CLW_KEYWORD=8 +val SCE_CLW_COMPILER_DIRECTIVE=9 +val SCE_CLW_RUNTIME_EXPRESSIONS=10 +val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=11 +val SCE_CLW_STRUCTURE_DATA_TYPE=12 +val SCE_CLW_ATTRIBUTE=13 +val SCE_CLW_STANDARD_EQUATE=14 +val SCE_CLW_ERROR=15 +val SCE_CLW_DEPRECATED=16 +# Lexical states for SCLEX_LOT +lex LOT=SCLEX_LOT SCE_LOT_ +val SCE_LOT_DEFAULT=0 +val SCE_LOT_HEADER=1 +val SCE_LOT_BREAK=2 +val SCE_LOT_SET=3 +val SCE_LOT_PASS=4 +val SCE_LOT_FAIL=5 +val SCE_LOT_ABORT=6 +# Lexical states for SCLEX_YAML +lex YAML=SCLEX_YAML SCE_YAML_ +val SCE_YAML_DEFAULT=0 +val SCE_YAML_COMMENT=1 +val SCE_YAML_IDENTIFIER=2 +val SCE_YAML_KEYWORD=3 +val SCE_YAML_NUMBER=4 +val SCE_YAML_REFERENCE=5 +val SCE_YAML_DOCUMENT=6 +val SCE_YAML_TEXT=7 +val SCE_YAML_ERROR=8 +val SCE_YAML_OPERATOR=9 +# Lexical states for SCLEX_TEX +lex TeX=SCLEX_TEX SCE_TEX_ +val SCE_TEX_DEFAULT=0 +val SCE_TEX_SPECIAL=1 +val SCE_TEX_GROUP=2 +val SCE_TEX_SYMBOL=3 +val SCE_TEX_COMMAND=4 +val SCE_TEX_TEXT=5 +lex Metapost=SCLEX_METAPOST SCE_METAPOST_ +val SCE_METAPOST_DEFAULT=0 +val SCE_METAPOST_SPECIAL=1 +val SCE_METAPOST_GROUP=2 +val SCE_METAPOST_SYMBOL=3 +val SCE_METAPOST_COMMAND=4 +val SCE_METAPOST_TEXT=5 +val SCE_METAPOST_EXTRA=6 +# Lexical states for SCLEX_ERLANG +lex Erlang=SCLEX_ERLANG SCE_ERLANG_ +val SCE_ERLANG_DEFAULT=0 +val SCE_ERLANG_COMMENT=1 +val SCE_ERLANG_VARIABLE=2 +val SCE_ERLANG_NUMBER=3 +val SCE_ERLANG_KEYWORD=4 +val SCE_ERLANG_STRING=5 +val SCE_ERLANG_OPERATOR=6 +val SCE_ERLANG_ATOM=7 +val SCE_ERLANG_FUNCTION_NAME=8 +val SCE_ERLANG_CHARACTER=9 +val SCE_ERLANG_MACRO=10 +val SCE_ERLANG_RECORD=11 +val SCE_ERLANG_PREPROC=12 +val SCE_ERLANG_NODE_NAME=13 +val SCE_ERLANG_COMMENT_FUNCTION=14 +val SCE_ERLANG_COMMENT_MODULE=15 +val SCE_ERLANG_COMMENT_DOC=16 +val SCE_ERLANG_COMMENT_DOC_MACRO=17 +val SCE_ERLANG_ATOM_QUOTED=18 +val SCE_ERLANG_MACRO_QUOTED=19 +val SCE_ERLANG_RECORD_QUOTED=20 +val SCE_ERLANG_NODE_NAME_QUOTED=21 +val SCE_ERLANG_BIFS=22 +val SCE_ERLANG_MODULES=23 +val SCE_ERLANG_MODULES_ATT=24 +val SCE_ERLANG_UNKNOWN=31 +# Lexical states for SCLEX_OCTAVE are identical to MatLab +lex Octave=SCLEX_OCTAVE SCE_MATLAB_ +# Lexical states for SCLEX_JULIA +lex Julia=SCLEX_JULIA SCE_JULIA_ +val SCE_JULIA_DEFAULT=0 +val SCE_JULIA_COMMENT=1 +val SCE_JULIA_NUMBER=2 +val SCE_JULIA_KEYWORD1=3 +val SCE_JULIA_KEYWORD2=4 +val SCE_JULIA_KEYWORD3=5 +val SCE_JULIA_CHAR=6 +val SCE_JULIA_OPERATOR=7 +val SCE_JULIA_BRACKET=8 +val SCE_JULIA_IDENTIFIER=9 +val SCE_JULIA_STRING=10 +val SCE_JULIA_SYMBOL=11 +val SCE_JULIA_MACRO=12 +val SCE_JULIA_STRINGINTERP=13 +val SCE_JULIA_DOCSTRING=14 +val SCE_JULIA_STRINGLITERAL=15 +val SCE_JULIA_COMMAND=16 +val SCE_JULIA_COMMANDLITERAL=17 +val SCE_JULIA_TYPEANNOT=18 +val SCE_JULIA_LEXERROR=19 +val SCE_JULIA_KEYWORD4=20 +val SCE_JULIA_TYPEOPERATOR=21 +# Lexical states for SCLEX_MSSQL +lex MSSQL=SCLEX_MSSQL SCE_MSSQL_ +val SCE_MSSQL_DEFAULT=0 +val SCE_MSSQL_COMMENT=1 +val SCE_MSSQL_LINE_COMMENT=2 +val SCE_MSSQL_NUMBER=3 +val SCE_MSSQL_STRING=4 +val SCE_MSSQL_OPERATOR=5 +val SCE_MSSQL_IDENTIFIER=6 +val SCE_MSSQL_VARIABLE=7 +val SCE_MSSQL_COLUMN_NAME=8 +val SCE_MSSQL_STATEMENT=9 +val SCE_MSSQL_DATATYPE=10 +val SCE_MSSQL_SYSTABLE=11 +val SCE_MSSQL_GLOBAL_VARIABLE=12 +val SCE_MSSQL_FUNCTION=13 +val SCE_MSSQL_STORED_PROCEDURE=14 +val SCE_MSSQL_DEFAULT_PREF_DATATYPE=15 +val SCE_MSSQL_COLUMN_NAME_2=16 +# Lexical states for SCLEX_VERILOG +lex Verilog=SCLEX_VERILOG SCE_V_ +val SCE_V_DEFAULT=0 +val SCE_V_COMMENT=1 +val SCE_V_COMMENTLINE=2 +val SCE_V_COMMENTLINEBANG=3 +val SCE_V_NUMBER=4 +val SCE_V_WORD=5 +val SCE_V_STRING=6 +val SCE_V_WORD2=7 +val SCE_V_WORD3=8 +val SCE_V_PREPROCESSOR=9 +val SCE_V_OPERATOR=10 +val SCE_V_IDENTIFIER=11 +val SCE_V_STRINGEOL=12 +val SCE_V_USER=19 +val SCE_V_COMMENT_WORD=20 +val SCE_V_INPUT=21 +val SCE_V_OUTPUT=22 +val SCE_V_INOUT=23 +val SCE_V_PORT_CONNECT=24 +# Lexical states for SCLEX_KIX +lex Kix=SCLEX_KIX SCE_KIX_ +val SCE_KIX_DEFAULT=0 +val SCE_KIX_COMMENT=1 +val SCE_KIX_STRING1=2 +val SCE_KIX_STRING2=3 +val SCE_KIX_NUMBER=4 +val SCE_KIX_VAR=5 +val SCE_KIX_MACRO=6 +val SCE_KIX_KEYWORD=7 +val SCE_KIX_FUNCTIONS=8 +val SCE_KIX_OPERATOR=9 +val SCE_KIX_COMMENTSTREAM=10 +val SCE_KIX_IDENTIFIER=31 +# Lexical states for SCLEX_GUI4CLI +lex Gui4Cli=SCLEX_GUI4CLI SCE_GC_ +val SCE_GC_DEFAULT=0 +val SCE_GC_COMMENTLINE=1 +val SCE_GC_COMMENTBLOCK=2 +val SCE_GC_GLOBAL=3 +val SCE_GC_EVENT=4 +val SCE_GC_ATTRIBUTE=5 +val SCE_GC_CONTROL=6 +val SCE_GC_COMMAND=7 +val SCE_GC_STRING=8 +val SCE_GC_OPERATOR=9 +# Lexical states for SCLEX_SPECMAN +lex Specman=SCLEX_SPECMAN SCE_SN_ +val SCE_SN_DEFAULT=0 +val SCE_SN_CODE=1 +val SCE_SN_COMMENTLINE=2 +val SCE_SN_COMMENTLINEBANG=3 +val SCE_SN_NUMBER=4 +val SCE_SN_WORD=5 +val SCE_SN_STRING=6 +val SCE_SN_WORD2=7 +val SCE_SN_WORD3=8 +val SCE_SN_PREPROCESSOR=9 +val SCE_SN_OPERATOR=10 +val SCE_SN_IDENTIFIER=11 +val SCE_SN_STRINGEOL=12 +val SCE_SN_REGEXTAG=13 +val SCE_SN_SIGNAL=14 +val SCE_SN_USER=19 +# Lexical states for SCLEX_AU3 +lex Au3=SCLEX_AU3 SCE_AU3_ +val SCE_AU3_DEFAULT=0 +val SCE_AU3_COMMENT=1 +val SCE_AU3_COMMENTBLOCK=2 +val SCE_AU3_NUMBER=3 +val SCE_AU3_FUNCTION=4 +val SCE_AU3_KEYWORD=5 +val SCE_AU3_MACRO=6 +val SCE_AU3_STRING=7 +val SCE_AU3_OPERATOR=8 +val SCE_AU3_VARIABLE=9 +val SCE_AU3_SENT=10 +val SCE_AU3_PREPROCESSOR=11 +val SCE_AU3_SPECIAL=12 +val SCE_AU3_EXPAND=13 +val SCE_AU3_COMOBJ=14 +val SCE_AU3_UDF=15 +# Lexical states for SCLEX_APDL +lex APDL=SCLEX_APDL SCE_APDL_ +val SCE_APDL_DEFAULT=0 +val SCE_APDL_COMMENT=1 +val SCE_APDL_COMMENTBLOCK=2 +val SCE_APDL_NUMBER=3 +val SCE_APDL_STRING=4 +val SCE_APDL_OPERATOR=5 +val SCE_APDL_WORD=6 +val SCE_APDL_PROCESSOR=7 +val SCE_APDL_COMMAND=8 +val SCE_APDL_SLASHCOMMAND=9 +val SCE_APDL_STARCOMMAND=10 +val SCE_APDL_ARGUMENT=11 +val SCE_APDL_FUNCTION=12 +# Lexical states for SCLEX_BASH +lex Bash=SCLEX_BASH SCE_SH_ +val SCE_SH_DEFAULT=0 +val SCE_SH_ERROR=1 +val SCE_SH_COMMENTLINE=2 +val SCE_SH_NUMBER=3 +val SCE_SH_WORD=4 +val SCE_SH_STRING=5 +val SCE_SH_CHARACTER=6 +val SCE_SH_OPERATOR=7 +val SCE_SH_IDENTIFIER=8 +val SCE_SH_SCALAR=9 +val SCE_SH_PARAM=10 +val SCE_SH_BACKTICKS=11 +val SCE_SH_HERE_DELIM=12 +val SCE_SH_HERE_Q=13 +# Lexical states for SCLEX_ASN1 +lex Asn1=SCLEX_ASN1 SCE_ASN1_ +val SCE_ASN1_DEFAULT=0 +val SCE_ASN1_COMMENT=1 +val SCE_ASN1_IDENTIFIER=2 +val SCE_ASN1_STRING=3 +val SCE_ASN1_OID=4 +val SCE_ASN1_SCALAR=5 +val SCE_ASN1_KEYWORD=6 +val SCE_ASN1_ATTRIBUTE=7 +val SCE_ASN1_DESCRIPTOR=8 +val SCE_ASN1_TYPE=9 +val SCE_ASN1_OPERATOR=10 +# Lexical states for SCLEX_VHDL +lex VHDL=SCLEX_VHDL SCE_VHDL_ +val SCE_VHDL_DEFAULT=0 +val SCE_VHDL_COMMENT=1 +val SCE_VHDL_COMMENTLINEBANG=2 +val SCE_VHDL_NUMBER=3 +val SCE_VHDL_STRING=4 +val SCE_VHDL_OPERATOR=5 +val SCE_VHDL_IDENTIFIER=6 +val SCE_VHDL_STRINGEOL=7 +val SCE_VHDL_KEYWORD=8 +val SCE_VHDL_STDOPERATOR=9 +val SCE_VHDL_ATTRIBUTE=10 +val SCE_VHDL_STDFUNCTION=11 +val SCE_VHDL_STDPACKAGE=12 +val SCE_VHDL_STDTYPE=13 +val SCE_VHDL_USERWORD=14 +val SCE_VHDL_BLOCK_COMMENT=15 +# Lexical states for SCLEX_CAML +lex Caml=SCLEX_CAML SCE_CAML_ +val SCE_CAML_DEFAULT=0 +val SCE_CAML_IDENTIFIER=1 +val SCE_CAML_TAGNAME=2 +val SCE_CAML_KEYWORD=3 +val SCE_CAML_KEYWORD2=4 +val SCE_CAML_KEYWORD3=5 +val SCE_CAML_LINENUM=6 +val SCE_CAML_OPERATOR=7 +val SCE_CAML_NUMBER=8 +val SCE_CAML_CHAR=9 +val SCE_CAML_WHITE=10 +val SCE_CAML_STRING=11 +val SCE_CAML_COMMENT=12 +val SCE_CAML_COMMENT1=13 +val SCE_CAML_COMMENT2=14 +val SCE_CAML_COMMENT3=15 +# Lexical states for SCLEX_HASKELL +lex Haskell=SCLEX_HASKELL SCE_HA_ +val SCE_HA_DEFAULT=0 +val SCE_HA_IDENTIFIER=1 +val SCE_HA_KEYWORD=2 +val SCE_HA_NUMBER=3 +val SCE_HA_STRING=4 +val SCE_HA_CHARACTER=5 +val SCE_HA_CLASS=6 +val SCE_HA_MODULE=7 +val SCE_HA_CAPITAL=8 +val SCE_HA_DATA=9 +val SCE_HA_IMPORT=10 +val SCE_HA_OPERATOR=11 +val SCE_HA_INSTANCE=12 +val SCE_HA_COMMENTLINE=13 +val SCE_HA_COMMENTBLOCK=14 +val SCE_HA_COMMENTBLOCK2=15 +val SCE_HA_COMMENTBLOCK3=16 +val SCE_HA_PRAGMA=17 +val SCE_HA_PREPROCESSOR=18 +val SCE_HA_STRINGEOL=19 +val SCE_HA_RESERVED_OPERATOR=20 +val SCE_HA_LITERATE_COMMENT=21 +val SCE_HA_LITERATE_CODEDELIM=22 +# Lexical states of SCLEX_TADS3 +lex TADS3=SCLEX_TADS3 SCE_T3_ +val SCE_T3_DEFAULT=0 +val SCE_T3_X_DEFAULT=1 +val SCE_T3_PREPROCESSOR=2 +val SCE_T3_BLOCK_COMMENT=3 +val SCE_T3_LINE_COMMENT=4 +val SCE_T3_OPERATOR=5 +val SCE_T3_KEYWORD=6 +val SCE_T3_NUMBER=7 +val SCE_T3_IDENTIFIER=8 +val SCE_T3_S_STRING=9 +val SCE_T3_D_STRING=10 +val SCE_T3_X_STRING=11 +val SCE_T3_LIB_DIRECTIVE=12 +val SCE_T3_MSG_PARAM=13 +val SCE_T3_HTML_TAG=14 +val SCE_T3_HTML_DEFAULT=15 +val SCE_T3_HTML_STRING=16 +val SCE_T3_USER1=17 +val SCE_T3_USER2=18 +val SCE_T3_USER3=19 +val SCE_T3_BRACE=20 +# Lexical states for SCLEX_REBOL +lex Rebol=SCLEX_REBOL SCE_REBOL_ +val SCE_REBOL_DEFAULT=0 +val SCE_REBOL_COMMENTLINE=1 +val SCE_REBOL_COMMENTBLOCK=2 +val SCE_REBOL_PREFACE=3 +val SCE_REBOL_OPERATOR=4 +val SCE_REBOL_CHARACTER=5 +val SCE_REBOL_QUOTEDSTRING=6 +val SCE_REBOL_BRACEDSTRING=7 +val SCE_REBOL_NUMBER=8 +val SCE_REBOL_PAIR=9 +val SCE_REBOL_TUPLE=10 +val SCE_REBOL_BINARY=11 +val SCE_REBOL_MONEY=12 +val SCE_REBOL_ISSUE=13 +val SCE_REBOL_TAG=14 +val SCE_REBOL_FILE=15 +val SCE_REBOL_EMAIL=16 +val SCE_REBOL_URL=17 +val SCE_REBOL_DATE=18 +val SCE_REBOL_TIME=19 +val SCE_REBOL_IDENTIFIER=20 +val SCE_REBOL_WORD=21 +val SCE_REBOL_WORD2=22 +val SCE_REBOL_WORD3=23 +val SCE_REBOL_WORD4=24 +val SCE_REBOL_WORD5=25 +val SCE_REBOL_WORD6=26 +val SCE_REBOL_WORD7=27 +val SCE_REBOL_WORD8=28 +# Lexical states for SCLEX_SQL +lex SQL=SCLEX_SQL SCE_SQL_ +val SCE_SQL_DEFAULT=0 +val SCE_SQL_COMMENT=1 +val SCE_SQL_COMMENTLINE=2 +val SCE_SQL_COMMENTDOC=3 +val SCE_SQL_NUMBER=4 +val SCE_SQL_WORD=5 +val SCE_SQL_STRING=6 +val SCE_SQL_CHARACTER=7 +val SCE_SQL_SQLPLUS=8 +val SCE_SQL_SQLPLUS_PROMPT=9 +val SCE_SQL_OPERATOR=10 +val SCE_SQL_IDENTIFIER=11 +val SCE_SQL_SQLPLUS_COMMENT=13 +val SCE_SQL_COMMENTLINEDOC=15 +val SCE_SQL_WORD2=16 +val SCE_SQL_COMMENTDOCKEYWORD=17 +val SCE_SQL_COMMENTDOCKEYWORDERROR=18 +val SCE_SQL_USER1=19 +val SCE_SQL_USER2=20 +val SCE_SQL_USER3=21 +val SCE_SQL_USER4=22 +val SCE_SQL_QUOTEDIDENTIFIER=23 +val SCE_SQL_QOPERATOR=24 +# Lexical states for SCLEX_SMALLTALK +lex Smalltalk=SCLEX_SMALLTALK SCE_ST_ +val SCE_ST_DEFAULT=0 +val SCE_ST_STRING=1 +val SCE_ST_NUMBER=2 +val SCE_ST_COMMENT=3 +val SCE_ST_SYMBOL=4 +val SCE_ST_BINARY=5 +val SCE_ST_BOOL=6 +val SCE_ST_SELF=7 +val SCE_ST_SUPER=8 +val SCE_ST_NIL=9 +val SCE_ST_GLOBAL=10 +val SCE_ST_RETURN=11 +val SCE_ST_SPECIAL=12 +val SCE_ST_KWSEND=13 +val SCE_ST_ASSIGN=14 +val SCE_ST_CHARACTER=15 +val SCE_ST_SPEC_SEL=16 +# Lexical states for SCLEX_FLAGSHIP (clipper) +lex FlagShip=SCLEX_FLAGSHIP SCE_FS_ +val SCE_FS_DEFAULT=0 +val SCE_FS_COMMENT=1 +val SCE_FS_COMMENTLINE=2 +val SCE_FS_COMMENTDOC=3 +val SCE_FS_COMMENTLINEDOC=4 +val SCE_FS_COMMENTDOCKEYWORD=5 +val SCE_FS_COMMENTDOCKEYWORDERROR=6 +val SCE_FS_KEYWORD=7 +val SCE_FS_KEYWORD2=8 +val SCE_FS_KEYWORD3=9 +val SCE_FS_KEYWORD4=10 +val SCE_FS_NUMBER=11 +val SCE_FS_STRING=12 +val SCE_FS_PREPROCESSOR=13 +val SCE_FS_OPERATOR=14 +val SCE_FS_IDENTIFIER=15 +val SCE_FS_DATE=16 +val SCE_FS_STRINGEOL=17 +val SCE_FS_CONSTANT=18 +val SCE_FS_WORDOPERATOR=19 +val SCE_FS_DISABLEDCODE=20 +val SCE_FS_DEFAULT_C=21 +val SCE_FS_COMMENTDOC_C=22 +val SCE_FS_COMMENTLINEDOC_C=23 +val SCE_FS_KEYWORD_C=24 +val SCE_FS_KEYWORD2_C=25 +val SCE_FS_NUMBER_C=26 +val SCE_FS_STRING_C=27 +val SCE_FS_PREPROCESSOR_C=28 +val SCE_FS_OPERATOR_C=29 +val SCE_FS_IDENTIFIER_C=30 +val SCE_FS_STRINGEOL_C=31 +# Lexical states for SCLEX_CSOUND +lex Csound=SCLEX_CSOUND SCE_CSOUND_ +val SCE_CSOUND_DEFAULT=0 +val SCE_CSOUND_COMMENT=1 +val SCE_CSOUND_NUMBER=2 +val SCE_CSOUND_OPERATOR=3 +val SCE_CSOUND_INSTR=4 +val SCE_CSOUND_IDENTIFIER=5 +val SCE_CSOUND_OPCODE=6 +val SCE_CSOUND_HEADERSTMT=7 +val SCE_CSOUND_USERKEYWORD=8 +val SCE_CSOUND_COMMENTBLOCK=9 +val SCE_CSOUND_PARAM=10 +val SCE_CSOUND_ARATE_VAR=11 +val SCE_CSOUND_KRATE_VAR=12 +val SCE_CSOUND_IRATE_VAR=13 +val SCE_CSOUND_GLOBAL_VAR=14 +val SCE_CSOUND_STRINGEOL=15 +# Lexical states for SCLEX_INNOSETUP +lex Inno=SCLEX_INNOSETUP SCE_INNO_ +val SCE_INNO_DEFAULT=0 +val SCE_INNO_COMMENT=1 +val SCE_INNO_KEYWORD=2 +val SCE_INNO_PARAMETER=3 +val SCE_INNO_SECTION=4 +val SCE_INNO_PREPROC=5 +val SCE_INNO_INLINE_EXPANSION=6 +val SCE_INNO_COMMENT_PASCAL=7 +val SCE_INNO_KEYWORD_PASCAL=8 +val SCE_INNO_KEYWORD_USER=9 +val SCE_INNO_STRING_DOUBLE=10 +val SCE_INNO_STRING_SINGLE=11 +val SCE_INNO_IDENTIFIER=12 +# Lexical states for SCLEX_OPAL +lex Opal=SCLEX_OPAL SCE_OPAL_ +val SCE_OPAL_SPACE=0 +val SCE_OPAL_COMMENT_BLOCK=1 +val SCE_OPAL_COMMENT_LINE=2 +val SCE_OPAL_INTEGER=3 +val SCE_OPAL_KEYWORD=4 +val SCE_OPAL_SORT=5 +val SCE_OPAL_STRING=6 +val SCE_OPAL_PAR=7 +val SCE_OPAL_BOOL_CONST=8 +val SCE_OPAL_DEFAULT=32 +# Lexical states for SCLEX_SPICE +lex Spice=SCLEX_SPICE SCE_SPICE_ +val SCE_SPICE_DEFAULT=0 +val SCE_SPICE_IDENTIFIER=1 +val SCE_SPICE_KEYWORD=2 +val SCE_SPICE_KEYWORD2=3 +val SCE_SPICE_KEYWORD3=4 +val SCE_SPICE_NUMBER=5 +val SCE_SPICE_DELIMITER=6 +val SCE_SPICE_VALUE=7 +val SCE_SPICE_COMMENTLINE=8 +# Lexical states for SCLEX_CMAKE +lex CMAKE=SCLEX_CMAKE SCE_CMAKE_ +val SCE_CMAKE_DEFAULT=0 +val SCE_CMAKE_COMMENT=1 +val SCE_CMAKE_STRINGDQ=2 +val SCE_CMAKE_STRINGLQ=3 +val SCE_CMAKE_STRINGRQ=4 +val SCE_CMAKE_COMMANDS=5 +val SCE_CMAKE_PARAMETERS=6 +val SCE_CMAKE_VARIABLE=7 +val SCE_CMAKE_USERDEFINED=8 +val SCE_CMAKE_WHILEDEF=9 +val SCE_CMAKE_FOREACHDEF=10 +val SCE_CMAKE_IFDEFINEDEF=11 +val SCE_CMAKE_MACRODEF=12 +val SCE_CMAKE_STRINGVAR=13 +val SCE_CMAKE_NUMBER=14 +# Lexical states for SCLEX_GAP +lex Gap=SCLEX_GAP SCE_GAP_ +val SCE_GAP_DEFAULT=0 +val SCE_GAP_IDENTIFIER=1 +val SCE_GAP_KEYWORD=2 +val SCE_GAP_KEYWORD2=3 +val SCE_GAP_KEYWORD3=4 +val SCE_GAP_KEYWORD4=5 +val SCE_GAP_STRING=6 +val SCE_GAP_CHAR=7 +val SCE_GAP_OPERATOR=8 +val SCE_GAP_COMMENT=9 +val SCE_GAP_NUMBER=10 +val SCE_GAP_STRINGEOL=11 +# Lexical state for SCLEX_PLM +lex PLM=SCLEX_PLM SCE_PLM_ +val SCE_PLM_DEFAULT=0 +val SCE_PLM_COMMENT=1 +val SCE_PLM_STRING=2 +val SCE_PLM_NUMBER=3 +val SCE_PLM_IDENTIFIER=4 +val SCE_PLM_OPERATOR=5 +val SCE_PLM_CONTROL=6 +val SCE_PLM_KEYWORD=7 +# Lexical state for SCLEX_PROGRESS +lex Progress=SCLEX_PROGRESS SCE_ABL_ +val SCE_ABL_DEFAULT=0 +val SCE_ABL_NUMBER=1 +val SCE_ABL_WORD=2 +val SCE_ABL_STRING=3 +val SCE_ABL_CHARACTER=4 +val SCE_ABL_PREPROCESSOR=5 +val SCE_ABL_OPERATOR=6 +val SCE_ABL_IDENTIFIER=7 +val SCE_ABL_BLOCK=8 +val SCE_ABL_END=9 +val SCE_ABL_COMMENT=10 +val SCE_ABL_TASKMARKER=11 +val SCE_ABL_LINECOMMENT=12 +# Lexical states for SCLEX_ABAQUS +lex ABAQUS=SCLEX_ABAQUS SCE_ABAQUS_ +val SCE_ABAQUS_DEFAULT=0 +val SCE_ABAQUS_COMMENT=1 +val SCE_ABAQUS_COMMENTBLOCK=2 +val SCE_ABAQUS_NUMBER=3 +val SCE_ABAQUS_STRING=4 +val SCE_ABAQUS_OPERATOR=5 +val SCE_ABAQUS_WORD=6 +val SCE_ABAQUS_PROCESSOR=7 +val SCE_ABAQUS_COMMAND=8 +val SCE_ABAQUS_SLASHCOMMAND=9 +val SCE_ABAQUS_STARCOMMAND=10 +val SCE_ABAQUS_ARGUMENT=11 +val SCE_ABAQUS_FUNCTION=12 +# Lexical states for SCLEX_ASYMPTOTE +lex Asymptote=SCLEX_ASYMPTOTE SCE_ASY_ +val SCE_ASY_DEFAULT=0 +val SCE_ASY_COMMENT=1 +val SCE_ASY_COMMENTLINE=2 +val SCE_ASY_NUMBER=3 +val SCE_ASY_WORD=4 +val SCE_ASY_STRING=5 +val SCE_ASY_CHARACTER=6 +val SCE_ASY_OPERATOR=7 +val SCE_ASY_IDENTIFIER=8 +val SCE_ASY_STRINGEOL=9 +val SCE_ASY_COMMENTLINEDOC=10 +val SCE_ASY_WORD2=11 +# Lexical states for SCLEX_R +lex R=SCLEX_R SCE_R_ +val SCE_R_DEFAULT=0 +val SCE_R_COMMENT=1 +val SCE_R_KWORD=2 +val SCE_R_BASEKWORD=3 +val SCE_R_OTHERKWORD=4 +val SCE_R_NUMBER=5 +val SCE_R_STRING=6 +val SCE_R_STRING2=7 +val SCE_R_OPERATOR=8 +val SCE_R_IDENTIFIER=9 +val SCE_R_INFIX=10 +val SCE_R_INFIXEOL=11 +val SCE_R_BACKTICKS=12 +val SCE_R_RAWSTRING=13 +val SCE_R_RAWSTRING2=14 +val SCE_R_ESCAPESEQUENCE=15 +# Lexical state for SCLEX_MAGIK +lex MagikSF=SCLEX_MAGIK SCE_MAGIK_ +val SCE_MAGIK_DEFAULT=0 +val SCE_MAGIK_COMMENT=1 +val SCE_MAGIK_HYPER_COMMENT=16 +val SCE_MAGIK_STRING=2 +val SCE_MAGIK_CHARACTER=3 +val SCE_MAGIK_NUMBER=4 +val SCE_MAGIK_IDENTIFIER=5 +val SCE_MAGIK_OPERATOR=6 +val SCE_MAGIK_FLOW=7 +val SCE_MAGIK_CONTAINER=8 +val SCE_MAGIK_BRACKET_BLOCK=9 +val SCE_MAGIK_BRACE_BLOCK=10 +val SCE_MAGIK_SQBRACKET_BLOCK=11 +val SCE_MAGIK_UNKNOWN_KEYWORD=12 +val SCE_MAGIK_KEYWORD=13 +val SCE_MAGIK_PRAGMA=14 +val SCE_MAGIK_SYMBOL=15 +# Lexical state for SCLEX_POWERSHELL +lex PowerShell=SCLEX_POWERSHELL SCE_POWERSHELL_ +val SCE_POWERSHELL_DEFAULT=0 +val SCE_POWERSHELL_COMMENT=1 +val SCE_POWERSHELL_STRING=2 +val SCE_POWERSHELL_CHARACTER=3 +val SCE_POWERSHELL_NUMBER=4 +val SCE_POWERSHELL_VARIABLE=5 +val SCE_POWERSHELL_OPERATOR=6 +val SCE_POWERSHELL_IDENTIFIER=7 +val SCE_POWERSHELL_KEYWORD=8 +val SCE_POWERSHELL_CMDLET=9 +val SCE_POWERSHELL_ALIAS=10 +val SCE_POWERSHELL_FUNCTION=11 +val SCE_POWERSHELL_USER1=12 +val SCE_POWERSHELL_COMMENTSTREAM=13 +val SCE_POWERSHELL_HERE_STRING=14 +val SCE_POWERSHELL_HERE_CHARACTER=15 +val SCE_POWERSHELL_COMMENTDOCKEYWORD=16 +# Lexical state for SCLEX_MYSQL +lex MySQL=SCLEX_MYSQL SCE_MYSQL_ +val SCE_MYSQL_DEFAULT=0 +val SCE_MYSQL_COMMENT=1 +val SCE_MYSQL_COMMENTLINE=2 +val SCE_MYSQL_VARIABLE=3 +val SCE_MYSQL_SYSTEMVARIABLE=4 +val SCE_MYSQL_KNOWNSYSTEMVARIABLE=5 +val SCE_MYSQL_NUMBER=6 +val SCE_MYSQL_MAJORKEYWORD=7 +val SCE_MYSQL_KEYWORD=8 +val SCE_MYSQL_DATABASEOBJECT=9 +val SCE_MYSQL_PROCEDUREKEYWORD=10 +val SCE_MYSQL_STRING=11 +val SCE_MYSQL_SQSTRING=12 +val SCE_MYSQL_DQSTRING=13 +val SCE_MYSQL_OPERATOR=14 +val SCE_MYSQL_FUNCTION=15 +val SCE_MYSQL_IDENTIFIER=16 +val SCE_MYSQL_QUOTEDIDENTIFIER=17 +val SCE_MYSQL_USER1=18 +val SCE_MYSQL_USER2=19 +val SCE_MYSQL_USER3=20 +val SCE_MYSQL_HIDDENCOMMAND=21 +val SCE_MYSQL_PLACEHOLDER=22 +# Lexical state for SCLEX_PO +lex Po=SCLEX_PO SCE_PO_ +val SCE_PO_DEFAULT=0 +val SCE_PO_COMMENT=1 +val SCE_PO_MSGID=2 +val SCE_PO_MSGID_TEXT=3 +val SCE_PO_MSGSTR=4 +val SCE_PO_MSGSTR_TEXT=5 +val SCE_PO_MSGCTXT=6 +val SCE_PO_MSGCTXT_TEXT=7 +val SCE_PO_FUZZY=8 +val SCE_PO_PROGRAMMER_COMMENT=9 +val SCE_PO_REFERENCE=10 +val SCE_PO_FLAGS=11 +val SCE_PO_MSGID_TEXT_EOL=12 +val SCE_PO_MSGSTR_TEXT_EOL=13 +val SCE_PO_MSGCTXT_TEXT_EOL=14 +val SCE_PO_ERROR=15 +# Lexical states for SCLEX_PASCAL +lex Pascal=SCLEX_PASCAL SCE_PAS_ +val SCE_PAS_DEFAULT=0 +val SCE_PAS_IDENTIFIER=1 +val SCE_PAS_COMMENT=2 +val SCE_PAS_COMMENT2=3 +val SCE_PAS_COMMENTLINE=4 +val SCE_PAS_PREPROCESSOR=5 +val SCE_PAS_PREPROCESSOR2=6 +val SCE_PAS_NUMBER=7 +val SCE_PAS_HEXNUMBER=8 +val SCE_PAS_WORD=9 +val SCE_PAS_STRING=10 +val SCE_PAS_STRINGEOL=11 +val SCE_PAS_CHARACTER=12 +val SCE_PAS_OPERATOR=13 +val SCE_PAS_ASM=14 +# Lexical state for SCLEX_SORCUS +lex SORCUS=SCLEX_SORCUS SCE_SORCUS_ +val SCE_SORCUS_DEFAULT=0 +val SCE_SORCUS_COMMAND=1 +val SCE_SORCUS_PARAMETER=2 +val SCE_SORCUS_COMMENTLINE=3 +val SCE_SORCUS_STRING=4 +val SCE_SORCUS_STRINGEOL=5 +val SCE_SORCUS_IDENTIFIER=6 +val SCE_SORCUS_OPERATOR=7 +val SCE_SORCUS_NUMBER=8 +val SCE_SORCUS_CONSTANT=9 +# Lexical state for SCLEX_POWERPRO +lex PowerPro=SCLEX_POWERPRO SCE_POWERPRO_ +val SCE_POWERPRO_DEFAULT=0 +val SCE_POWERPRO_COMMENTBLOCK=1 +val SCE_POWERPRO_COMMENTLINE=2 +val SCE_POWERPRO_NUMBER=3 +val SCE_POWERPRO_WORD=4 +val SCE_POWERPRO_WORD2=5 +val SCE_POWERPRO_WORD3=6 +val SCE_POWERPRO_WORD4=7 +val SCE_POWERPRO_DOUBLEQUOTEDSTRING=8 +val SCE_POWERPRO_SINGLEQUOTEDSTRING=9 +val SCE_POWERPRO_LINECONTINUE=10 +val SCE_POWERPRO_OPERATOR=11 +val SCE_POWERPRO_IDENTIFIER=12 +val SCE_POWERPRO_STRINGEOL=13 +val SCE_POWERPRO_VERBATIM=14 +val SCE_POWERPRO_ALTQUOTE=15 +val SCE_POWERPRO_FUNCTION=16 +# Lexical states for SCLEX_SML +lex SML=SCLEX_SML SCE_SML_ +val SCE_SML_DEFAULT=0 +val SCE_SML_IDENTIFIER=1 +val SCE_SML_TAGNAME=2 +val SCE_SML_KEYWORD=3 +val SCE_SML_KEYWORD2=4 +val SCE_SML_KEYWORD3=5 +val SCE_SML_LINENUM=6 +val SCE_SML_OPERATOR=7 +val SCE_SML_NUMBER=8 +val SCE_SML_CHAR=9 +val SCE_SML_STRING=11 +val SCE_SML_COMMENT=12 +val SCE_SML_COMMENT1=13 +val SCE_SML_COMMENT2=14 +val SCE_SML_COMMENT3=15 +# Lexical state for SCLEX_MARKDOWN +lex Markdown=SCLEX_MARKDOWN SCE_MARKDOWN_ +val SCE_MARKDOWN_DEFAULT=0 +val SCE_MARKDOWN_LINE_BEGIN=1 +val SCE_MARKDOWN_STRONG1=2 +val SCE_MARKDOWN_STRONG2=3 +val SCE_MARKDOWN_EM1=4 +val SCE_MARKDOWN_EM2=5 +val SCE_MARKDOWN_HEADER1=6 +val SCE_MARKDOWN_HEADER2=7 +val SCE_MARKDOWN_HEADER3=8 +val SCE_MARKDOWN_HEADER4=9 +val SCE_MARKDOWN_HEADER5=10 +val SCE_MARKDOWN_HEADER6=11 +val SCE_MARKDOWN_PRECHAR=12 +val SCE_MARKDOWN_ULIST_ITEM=13 +val SCE_MARKDOWN_OLIST_ITEM=14 +val SCE_MARKDOWN_BLOCKQUOTE=15 +val SCE_MARKDOWN_STRIKEOUT=16 +val SCE_MARKDOWN_HRULE=17 +val SCE_MARKDOWN_LINK=18 +val SCE_MARKDOWN_CODE=19 +val SCE_MARKDOWN_CODE2=20 +val SCE_MARKDOWN_CODEBK=21 +# Lexical state for SCLEX_TXT2TAGS +lex Txt2tags=SCLEX_TXT2TAGS SCE_TXT2TAGS_ +val SCE_TXT2TAGS_DEFAULT=0 +val SCE_TXT2TAGS_LINE_BEGIN=1 +val SCE_TXT2TAGS_STRONG1=2 +val SCE_TXT2TAGS_STRONG2=3 +val SCE_TXT2TAGS_EM1=4 +val SCE_TXT2TAGS_EM2=5 +val SCE_TXT2TAGS_HEADER1=6 +val SCE_TXT2TAGS_HEADER2=7 +val SCE_TXT2TAGS_HEADER3=8 +val SCE_TXT2TAGS_HEADER4=9 +val SCE_TXT2TAGS_HEADER5=10 +val SCE_TXT2TAGS_HEADER6=11 +val SCE_TXT2TAGS_PRECHAR=12 +val SCE_TXT2TAGS_ULIST_ITEM=13 +val SCE_TXT2TAGS_OLIST_ITEM=14 +val SCE_TXT2TAGS_BLOCKQUOTE=15 +val SCE_TXT2TAGS_STRIKEOUT=16 +val SCE_TXT2TAGS_HRULE=17 +val SCE_TXT2TAGS_LINK=18 +val SCE_TXT2TAGS_CODE=19 +val SCE_TXT2TAGS_CODE2=20 +val SCE_TXT2TAGS_CODEBK=21 +val SCE_TXT2TAGS_COMMENT=22 +val SCE_TXT2TAGS_OPTION=23 +val SCE_TXT2TAGS_PREPROC=24 +val SCE_TXT2TAGS_POSTPROC=25 +# Lexical states for SCLEX_A68K +lex A68k=SCLEX_A68K SCE_A68K_ +val SCE_A68K_DEFAULT=0 +val SCE_A68K_COMMENT=1 +val SCE_A68K_NUMBER_DEC=2 +val SCE_A68K_NUMBER_BIN=3 +val SCE_A68K_NUMBER_HEX=4 +val SCE_A68K_STRING1=5 +val SCE_A68K_OPERATOR=6 +val SCE_A68K_CPUINSTRUCTION=7 +val SCE_A68K_EXTINSTRUCTION=8 +val SCE_A68K_REGISTER=9 +val SCE_A68K_DIRECTIVE=10 +val SCE_A68K_MACRO_ARG=11 +val SCE_A68K_LABEL=12 +val SCE_A68K_STRING2=13 +val SCE_A68K_IDENTIFIER=14 +val SCE_A68K_MACRO_DECLARATION=15 +val SCE_A68K_COMMENT_WORD=16 +val SCE_A68K_COMMENT_SPECIAL=17 +val SCE_A68K_COMMENT_DOXYGEN=18 +# Lexical states for SCLEX_MODULA +lex Modula=SCLEX_MODULA SCE_MODULA_ +val SCE_MODULA_DEFAULT=0 +val SCE_MODULA_COMMENT=1 +val SCE_MODULA_DOXYCOMM=2 +val SCE_MODULA_DOXYKEY=3 +val SCE_MODULA_KEYWORD=4 +val SCE_MODULA_RESERVED=5 +val SCE_MODULA_NUMBER=6 +val SCE_MODULA_BASENUM=7 +val SCE_MODULA_FLOAT=8 +val SCE_MODULA_STRING=9 +val SCE_MODULA_STRSPEC=10 +val SCE_MODULA_CHAR=11 +val SCE_MODULA_CHARSPEC=12 +val SCE_MODULA_PROC=13 +val SCE_MODULA_PRAGMA=14 +val SCE_MODULA_PRGKEY=15 +val SCE_MODULA_OPERATOR=16 +val SCE_MODULA_BADSTR=17 +# Lexical states for SCLEX_COFFEESCRIPT +lex CoffeeScript=SCLEX_COFFEESCRIPT SCE_COFFEESCRIPT_ +val SCE_COFFEESCRIPT_DEFAULT=0 +val SCE_COFFEESCRIPT_COMMENT=1 +val SCE_COFFEESCRIPT_COMMENTLINE=2 +val SCE_COFFEESCRIPT_COMMENTDOC=3 +val SCE_COFFEESCRIPT_NUMBER=4 +val SCE_COFFEESCRIPT_WORD=5 +val SCE_COFFEESCRIPT_STRING=6 +val SCE_COFFEESCRIPT_CHARACTER=7 +val SCE_COFFEESCRIPT_UUID=8 +val SCE_COFFEESCRIPT_PREPROCESSOR=9 +val SCE_COFFEESCRIPT_OPERATOR=10 +val SCE_COFFEESCRIPT_IDENTIFIER=11 +val SCE_COFFEESCRIPT_STRINGEOL=12 +val SCE_COFFEESCRIPT_VERBATIM=13 +val SCE_COFFEESCRIPT_REGEX=14 +val SCE_COFFEESCRIPT_COMMENTLINEDOC=15 +val SCE_COFFEESCRIPT_WORD2=16 +val SCE_COFFEESCRIPT_COMMENTDOCKEYWORD=17 +val SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR=18 +val SCE_COFFEESCRIPT_GLOBALCLASS=19 +val SCE_COFFEESCRIPT_STRINGRAW=20 +val SCE_COFFEESCRIPT_TRIPLEVERBATIM=21 +val SCE_COFFEESCRIPT_COMMENTBLOCK=22 +val SCE_COFFEESCRIPT_VERBOSE_REGEX=23 +val SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT=24 +val SCE_COFFEESCRIPT_INSTANCEPROPERTY=25 +# Lexical states for SCLEX_AVS +lex AVS=SCLEX_AVS SCE_AVS_ +val SCE_AVS_DEFAULT=0 +val SCE_AVS_COMMENTBLOCK=1 +val SCE_AVS_COMMENTBLOCKN=2 +val SCE_AVS_COMMENTLINE=3 +val SCE_AVS_NUMBER=4 +val SCE_AVS_OPERATOR=5 +val SCE_AVS_IDENTIFIER=6 +val SCE_AVS_STRING=7 +val SCE_AVS_TRIPLESTRING=8 +val SCE_AVS_KEYWORD=9 +val SCE_AVS_FILTER=10 +val SCE_AVS_PLUGIN=11 +val SCE_AVS_FUNCTION=12 +val SCE_AVS_CLIPPROP=13 +val SCE_AVS_USERDFN=14 +# Lexical states for SCLEX_ECL +lex ECL=SCLEX_ECL SCE_ECL_ +val SCE_ECL_DEFAULT=0 +val SCE_ECL_COMMENT=1 +val SCE_ECL_COMMENTLINE=2 +val SCE_ECL_NUMBER=3 +val SCE_ECL_STRING=4 +val SCE_ECL_WORD0=5 +val SCE_ECL_OPERATOR=6 +val SCE_ECL_CHARACTER=7 +val SCE_ECL_UUID=8 +val SCE_ECL_PREPROCESSOR=9 +val SCE_ECL_UNKNOWN=10 +val SCE_ECL_IDENTIFIER=11 +val SCE_ECL_STRINGEOL=12 +val SCE_ECL_VERBATIM=13 +val SCE_ECL_REGEX=14 +val SCE_ECL_COMMENTLINEDOC=15 +val SCE_ECL_WORD1=16 +val SCE_ECL_COMMENTDOCKEYWORD=17 +val SCE_ECL_COMMENTDOCKEYWORDERROR=18 +val SCE_ECL_WORD2=19 +val SCE_ECL_WORD3=20 +val SCE_ECL_WORD4=21 +val SCE_ECL_WORD5=22 +val SCE_ECL_COMMENTDOC=23 +val SCE_ECL_ADDED=24 +val SCE_ECL_DELETED=25 +val SCE_ECL_CHANGED=26 +val SCE_ECL_MOVED=27 +# Lexical states for SCLEX_OSCRIPT +lex OScript=SCLEX_OSCRIPT SCE_OSCRIPT_ +val SCE_OSCRIPT_DEFAULT=0 +val SCE_OSCRIPT_LINE_COMMENT=1 +val SCE_OSCRIPT_BLOCK_COMMENT=2 +val SCE_OSCRIPT_DOC_COMMENT=3 +val SCE_OSCRIPT_PREPROCESSOR=4 +val SCE_OSCRIPT_NUMBER=5 +val SCE_OSCRIPT_SINGLEQUOTE_STRING=6 +val SCE_OSCRIPT_DOUBLEQUOTE_STRING=7 +val SCE_OSCRIPT_CONSTANT=8 +val SCE_OSCRIPT_IDENTIFIER=9 +val SCE_OSCRIPT_GLOBAL=10 +val SCE_OSCRIPT_KEYWORD=11 +val SCE_OSCRIPT_OPERATOR=12 +val SCE_OSCRIPT_LABEL=13 +val SCE_OSCRIPT_TYPE=14 +val SCE_OSCRIPT_FUNCTION=15 +val SCE_OSCRIPT_OBJECT=16 +val SCE_OSCRIPT_PROPERTY=17 +val SCE_OSCRIPT_METHOD=18 +# Lexical states for SCLEX_VISUALPROLOG +lex VisualProlog=SCLEX_VISUALPROLOG SCE_VISUALPROLOG_ +val SCE_VISUALPROLOG_DEFAULT=0 +val SCE_VISUALPROLOG_KEY_MAJOR=1 +val SCE_VISUALPROLOG_KEY_MINOR=2 +val SCE_VISUALPROLOG_KEY_DIRECTIVE=3 +val SCE_VISUALPROLOG_COMMENT_BLOCK=4 +val SCE_VISUALPROLOG_COMMENT_LINE=5 +val SCE_VISUALPROLOG_COMMENT_KEY=6 +val SCE_VISUALPROLOG_COMMENT_KEY_ERROR=7 +val SCE_VISUALPROLOG_IDENTIFIER=8 +val SCE_VISUALPROLOG_VARIABLE=9 +val SCE_VISUALPROLOG_ANONYMOUS=10 +val SCE_VISUALPROLOG_NUMBER=11 +val SCE_VISUALPROLOG_OPERATOR=12 +val SCE_VISUALPROLOG_UNUSED1=13 +val SCE_VISUALPROLOG_UNUSED2=14 +val SCE_VISUALPROLOG_UNUSED3=15 +val SCE_VISUALPROLOG_STRING_QUOTE=16 +val SCE_VISUALPROLOG_STRING_ESCAPE=17 +val SCE_VISUALPROLOG_STRING_ESCAPE_ERROR=18 +val SCE_VISUALPROLOG_UNUSED4=19 +val SCE_VISUALPROLOG_STRING=20 +val SCE_VISUALPROLOG_UNUSED5=21 +val SCE_VISUALPROLOG_STRING_EOL=22 +val SCE_VISUALPROLOG_EMBEDDED=23 +val SCE_VISUALPROLOG_PLACEHOLDER=24 +# Lexical states for SCLEX_STTXT +lex StructuredText=SCLEX_STTXT SCE_STTXT_ +val SCE_STTXT_DEFAULT=0 +val SCE_STTXT_COMMENT=1 +val SCE_STTXT_COMMENTLINE=2 +val SCE_STTXT_KEYWORD=3 +val SCE_STTXT_TYPE=4 +val SCE_STTXT_FUNCTION=5 +val SCE_STTXT_FB=6 +val SCE_STTXT_NUMBER=7 +val SCE_STTXT_HEXNUMBER=8 +val SCE_STTXT_PRAGMA=9 +val SCE_STTXT_OPERATOR=10 +val SCE_STTXT_CHARACTER=11 +val SCE_STTXT_STRING1=12 +val SCE_STTXT_STRING2=13 +val SCE_STTXT_STRINGEOL=14 +val SCE_STTXT_IDENTIFIER=15 +val SCE_STTXT_DATETIME=16 +val SCE_STTXT_VARS=17 +val SCE_STTXT_PRAGMAS=18 +# Lexical states for SCLEX_KVIRC +lex KVIrc=SCLEX_KVIRC SCE_KVIRC_ +val SCE_KVIRC_DEFAULT=0 +val SCE_KVIRC_COMMENT=1 +val SCE_KVIRC_COMMENTBLOCK=2 +val SCE_KVIRC_STRING=3 +val SCE_KVIRC_WORD=4 +val SCE_KVIRC_KEYWORD=5 +val SCE_KVIRC_FUNCTION_KEYWORD=6 +val SCE_KVIRC_FUNCTION=7 +val SCE_KVIRC_VARIABLE=8 +val SCE_KVIRC_NUMBER=9 +val SCE_KVIRC_OPERATOR=10 +val SCE_KVIRC_STRING_FUNCTION=11 +val SCE_KVIRC_STRING_VARIABLE=12 +# Lexical states for SCLEX_RUST +lex Rust=SCLEX_RUST SCE_RUST_ +val SCE_RUST_DEFAULT=0 +val SCE_RUST_COMMENTBLOCK=1 +val SCE_RUST_COMMENTLINE=2 +val SCE_RUST_COMMENTBLOCKDOC=3 +val SCE_RUST_COMMENTLINEDOC=4 +val SCE_RUST_NUMBER=5 +val SCE_RUST_WORD=6 +val SCE_RUST_WORD2=7 +val SCE_RUST_WORD3=8 +val SCE_RUST_WORD4=9 +val SCE_RUST_WORD5=10 +val SCE_RUST_WORD6=11 +val SCE_RUST_WORD7=12 +val SCE_RUST_STRING=13 +val SCE_RUST_STRINGR=14 +val SCE_RUST_CHARACTER=15 +val SCE_RUST_OPERATOR=16 +val SCE_RUST_IDENTIFIER=17 +val SCE_RUST_LIFETIME=18 +val SCE_RUST_MACRO=19 +val SCE_RUST_LEXERROR=20 +val SCE_RUST_BYTESTRING=21 +val SCE_RUST_BYTESTRINGR=22 +val SCE_RUST_BYTECHARACTER=23 +# Lexical states for SCLEX_DMAP +lex DMAP=SCLEX_DMAP SCE_DMAP_ +val SCE_DMAP_DEFAULT=0 +val SCE_DMAP_COMMENT=1 +val SCE_DMAP_NUMBER=2 +val SCE_DMAP_STRING1=3 +val SCE_DMAP_STRING2=4 +val SCE_DMAP_STRINGEOL=5 +val SCE_DMAP_OPERATOR=6 +val SCE_DMAP_IDENTIFIER=7 +val SCE_DMAP_WORD=8 +val SCE_DMAP_WORD2=9 +val SCE_DMAP_WORD3=10 +# Lexical states for SCLEX_DMIS +lex DMIS=SCLEX_DMIS SCE_DMIS_ +val SCE_DMIS_DEFAULT=0 +val SCE_DMIS_COMMENT=1 +val SCE_DMIS_STRING=2 +val SCE_DMIS_NUMBER=3 +val SCE_DMIS_KEYWORD=4 +val SCE_DMIS_MAJORWORD=5 +val SCE_DMIS_MINORWORD=6 +val SCE_DMIS_UNSUPPORTED_MAJOR=7 +val SCE_DMIS_UNSUPPORTED_MINOR=8 +val SCE_DMIS_LABEL=9 +# Lexical states for SCLEX_REGISTRY +lex REG=SCLEX_REGISTRY SCE_REG_ +val SCE_REG_DEFAULT=0 +val SCE_REG_COMMENT=1 +val SCE_REG_VALUENAME=2 +val SCE_REG_STRING=3 +val SCE_REG_HEXDIGIT=4 +val SCE_REG_VALUETYPE=5 +val SCE_REG_ADDEDKEY=6 +val SCE_REG_DELETEDKEY=7 +val SCE_REG_ESCAPED=8 +val SCE_REG_KEYPATH_GUID=9 +val SCE_REG_STRING_GUID=10 +val SCE_REG_PARAMETER=11 +val SCE_REG_OPERATOR=12 +# Lexical state for SCLEX_BIBTEX +lex BibTeX=SCLEX_BIBTEX SCE_BIBTEX_ +val SCE_BIBTEX_DEFAULT=0 +val SCE_BIBTEX_ENTRY=1 +val SCE_BIBTEX_UNKNOWN_ENTRY=2 +val SCE_BIBTEX_KEY=3 +val SCE_BIBTEX_PARAMETER=4 +val SCE_BIBTEX_VALUE=5 +val SCE_BIBTEX_COMMENT=6 +# Lexical state for SCLEX_SREC +lex Srec=SCLEX_SREC SCE_HEX_ +val SCE_HEX_DEFAULT=0 +val SCE_HEX_RECSTART=1 +val SCE_HEX_RECTYPE=2 +val SCE_HEX_RECTYPE_UNKNOWN=3 +val SCE_HEX_BYTECOUNT=4 +val SCE_HEX_BYTECOUNT_WRONG=5 +val SCE_HEX_NOADDRESS=6 +val SCE_HEX_DATAADDRESS=7 +val SCE_HEX_RECCOUNT=8 +val SCE_HEX_STARTADDRESS=9 +val SCE_HEX_ADDRESSFIELD_UNKNOWN=10 +val SCE_HEX_EXTENDEDADDRESS=11 +val SCE_HEX_DATA_ODD=12 +val SCE_HEX_DATA_EVEN=13 +val SCE_HEX_DATA_UNKNOWN=14 +val SCE_HEX_DATA_EMPTY=15 +val SCE_HEX_CHECKSUM=16 +val SCE_HEX_CHECKSUM_WRONG=17 +val SCE_HEX_GARBAGE=18 +# Lexical state for SCLEX_IHEX (shared with Srec) +lex IHex=SCLEX_IHEX SCE_HEX_ +# Lexical state for SCLEX_TEHEX (shared with Srec) +lex TEHex=SCLEX_TEHEX SCE_HEX_ +# Lexical states for SCLEX_JSON +lex JSON=SCLEX_JSON SCE_JSON_ +val SCE_JSON_DEFAULT=0 +val SCE_JSON_NUMBER=1 +val SCE_JSON_STRING=2 +val SCE_JSON_STRINGEOL=3 +val SCE_JSON_PROPERTYNAME=4 +val SCE_JSON_ESCAPESEQUENCE=5 +val SCE_JSON_LINECOMMENT=6 +val SCE_JSON_BLOCKCOMMENT=7 +val SCE_JSON_OPERATOR=8 +val SCE_JSON_URI=9 +val SCE_JSON_COMPACTIRI=10 +val SCE_JSON_KEYWORD=11 +val SCE_JSON_LDKEYWORD=12 +val SCE_JSON_ERROR=13 +lex EDIFACT=SCLEX_EDIFACT SCE_EDI_ +val SCE_EDI_DEFAULT=0 +val SCE_EDI_SEGMENTSTART=1 +val SCE_EDI_SEGMENTEND=2 +val SCE_EDI_SEP_ELEMENT=3 +val SCE_EDI_SEP_COMPOSITE=4 +val SCE_EDI_SEP_RELEASE=5 +val SCE_EDI_UNA=6 +val SCE_EDI_UNH=7 +val SCE_EDI_BADSEGMENT=8 +# Lexical states for SCLEX_STATA +lex STATA=SCLEX_STATA SCE_STATA_ +val SCE_STATA_DEFAULT=0 +val SCE_STATA_COMMENT=1 +val SCE_STATA_COMMENTLINE=2 +val SCE_STATA_COMMENTBLOCK=3 +val SCE_STATA_NUMBER=4 +val SCE_STATA_OPERATOR=5 +val SCE_STATA_IDENTIFIER=6 +val SCE_STATA_STRING=7 +val SCE_STATA_TYPE=8 +val SCE_STATA_WORD=9 +val SCE_STATA_GLOBAL_MACRO=10 +val SCE_STATA_MACRO=11 +# Lexical states for SCLEX_SAS +lex SAS=SCLEX_SAS SCE_SAS_ +val SCE_SAS_DEFAULT=0 +val SCE_SAS_COMMENT=1 +val SCE_SAS_COMMENTLINE=2 +val SCE_SAS_COMMENTBLOCK=3 +val SCE_SAS_NUMBER=4 +val SCE_SAS_OPERATOR=5 +val SCE_SAS_IDENTIFIER=6 +val SCE_SAS_STRING=7 +val SCE_SAS_TYPE=8 +val SCE_SAS_WORD=9 +val SCE_SAS_GLOBAL_MACRO=10 +val SCE_SAS_MACRO=11 +val SCE_SAS_MACRO_KEYWORD=12 +val SCE_SAS_BLOCK_KEYWORD=13 +val SCE_SAS_MACRO_FUNCTION=14 +val SCE_SAS_STATEMENT=15 +# Lexical states for SCLEX_NIM +lex Nim=SCLEX_NIM SCE_NIM_ +val SCE_NIM_DEFAULT=0 +val SCE_NIM_COMMENT=1 +val SCE_NIM_COMMENTDOC=2 +val SCE_NIM_COMMENTLINE=3 +val SCE_NIM_COMMENTLINEDOC=4 +val SCE_NIM_NUMBER=5 +val SCE_NIM_STRING=6 +val SCE_NIM_CHARACTER=7 +val SCE_NIM_WORD=8 +val SCE_NIM_TRIPLE=9 +val SCE_NIM_TRIPLEDOUBLE=10 +val SCE_NIM_BACKTICKS=11 +val SCE_NIM_FUNCNAME=12 +val SCE_NIM_STRINGEOL=13 +val SCE_NIM_NUMERROR=14 +val SCE_NIM_OPERATOR=15 +val SCE_NIM_IDENTIFIER=16 +# Lexical states for SCLEX_CIL +lex CIL=SCLEX_CIL SCE_CIL_ +val SCE_CIL_DEFAULT=0 +val SCE_CIL_COMMENT=1 +val SCE_CIL_COMMENTLINE=2 +val SCE_CIL_WORD=3 +val SCE_CIL_WORD2=4 +val SCE_CIL_WORD3=5 +val SCE_CIL_STRING=6 +val SCE_CIL_LABEL=7 +val SCE_CIL_OPERATOR=8 +val SCE_CIL_IDENTIFIER=9 +val SCE_CIL_STRINGEOL=10 +# Lexical states for SCLEX_X12 +lex X12=SCLEX_X12 SCE_X12_ +val SCE_X12_DEFAULT=0 +val SCE_X12_BAD=1 +val SCE_X12_ENVELOPE=2 +val SCE_X12_FUNCTIONGROUP=3 +val SCE_X12_TRANSACTIONSET=4 +val SCE_X12_SEGMENTHEADER=5 +val SCE_X12_SEGMENTEND=6 +val SCE_X12_SEP_ELEMENT=7 +val SCE_X12_SEP_SUBELEMENT=8 +# Lexical states for SCLEX_DATAFLEX +lex Dataflex=SCLEX_DATAFLEX SCE_DF_ +val SCE_DF_DEFAULT=0 +val SCE_DF_IDENTIFIER=1 +val SCE_DF_METATAG=2 +val SCE_DF_IMAGE=3 +val SCE_DF_COMMENTLINE=4 +val SCE_DF_PREPROCESSOR=5 +val SCE_DF_PREPROCESSOR2=6 +val SCE_DF_NUMBER=7 +val SCE_DF_HEXNUMBER=8 +val SCE_DF_WORD=9 +val SCE_DF_STRING=10 +val SCE_DF_STRINGEOL=11 +val SCE_DF_SCOPEWORD=12 +val SCE_DF_OPERATOR=13 +val SCE_DF_ICODE=14 +# Lexical states for SCLEX_HOLLYWOOD +lex Hollywood=SCLEX_HOLLYWOOD SCE_HOLLYWOOD_ +val SCE_HOLLYWOOD_DEFAULT=0 +val SCE_HOLLYWOOD_COMMENT=1 +val SCE_HOLLYWOOD_COMMENTBLOCK=2 +val SCE_HOLLYWOOD_NUMBER=3 +val SCE_HOLLYWOOD_KEYWORD=4 +val SCE_HOLLYWOOD_STDAPI=5 +val SCE_HOLLYWOOD_PLUGINAPI=6 +val SCE_HOLLYWOOD_PLUGINMETHOD=7 +val SCE_HOLLYWOOD_STRING=8 +val SCE_HOLLYWOOD_STRINGBLOCK=9 +val SCE_HOLLYWOOD_PREPROCESSOR=10 +val SCE_HOLLYWOOD_OPERATOR=11 +val SCE_HOLLYWOOD_IDENTIFIER=12 +val SCE_HOLLYWOOD_CONSTANT=13 +val SCE_HOLLYWOOD_HEXNUMBER=14 +# Lexical states for SCLEX_RAKU +lex Raku=SCLEX_RAKU SCE_RAKU_ +val SCE_RAKU_DEFAULT=0 +val SCE_RAKU_ERROR=1 +val SCE_RAKU_COMMENTLINE=2 +val SCE_RAKU_COMMENTEMBED=3 +val SCE_RAKU_POD=4 +val SCE_RAKU_CHARACTER=5 +val SCE_RAKU_HEREDOC_Q=6 +val SCE_RAKU_HEREDOC_QQ=7 +val SCE_RAKU_STRING=8 +val SCE_RAKU_STRING_Q=9 +val SCE_RAKU_STRING_QQ=10 +val SCE_RAKU_STRING_Q_LANG=11 +val SCE_RAKU_STRING_VAR=12 +val SCE_RAKU_REGEX=13 +val SCE_RAKU_REGEX_VAR=14 +val SCE_RAKU_ADVERB=15 +val SCE_RAKU_NUMBER=16 +val SCE_RAKU_PREPROCESSOR=17 +val SCE_RAKU_OPERATOR=18 +val SCE_RAKU_WORD=19 +val SCE_RAKU_FUNCTION=20 +val SCE_RAKU_IDENTIFIER=21 +val SCE_RAKU_TYPEDEF=22 +val SCE_RAKU_MU=23 +val SCE_RAKU_POSITIONAL=24 +val SCE_RAKU_ASSOCIATIVE=25 +val SCE_RAKU_CALLABLE=26 +val SCE_RAKU_GRAMMAR=27 +val SCE_RAKU_CLASS=28 +# Lexical states for SCLEX_FSHARP +lex FSharp=SCLEX_FSHARP SCE_FSHARP_ +val SCE_FSHARP_DEFAULT=0 +val SCE_FSHARP_KEYWORD=1 +val SCE_FSHARP_KEYWORD2=2 +val SCE_FSHARP_KEYWORD3=3 +val SCE_FSHARP_KEYWORD4=4 +val SCE_FSHARP_KEYWORD5=5 +val SCE_FSHARP_IDENTIFIER=6 +val SCE_FSHARP_QUOT_IDENTIFIER=7 +val SCE_FSHARP_COMMENT=8 +val SCE_FSHARP_COMMENTLINE=9 +val SCE_FSHARP_PREPROCESSOR=10 +val SCE_FSHARP_LINENUM=11 +val SCE_FSHARP_OPERATOR=12 +val SCE_FSHARP_NUMBER=13 +val SCE_FSHARP_CHARACTER=14 +val SCE_FSHARP_STRING=15 +val SCE_FSHARP_VERBATIM=16 +val SCE_FSHARP_QUOTATION=17 +val SCE_FSHARP_ATTRIBUTE=18 +val SCE_FSHARP_FORMAT_SPEC=19 +# Lexical states for SCLEX_ASCIIDOC +lex Asciidoc=SCLEX_ASCIIDOC SCE_ASCIIDOC_ +val SCE_ASCIIDOC_DEFAULT=0 +val SCE_ASCIIDOC_STRONG1=1 +val SCE_ASCIIDOC_STRONG2=2 +val SCE_ASCIIDOC_EM1=3 +val SCE_ASCIIDOC_EM2=4 +val SCE_ASCIIDOC_HEADER1=5 +val SCE_ASCIIDOC_HEADER2=6 +val SCE_ASCIIDOC_HEADER3=7 +val SCE_ASCIIDOC_HEADER4=8 +val SCE_ASCIIDOC_HEADER5=9 +val SCE_ASCIIDOC_HEADER6=10 +val SCE_ASCIIDOC_ULIST_ITEM=11 +val SCE_ASCIIDOC_OLIST_ITEM=12 +val SCE_ASCIIDOC_BLOCKQUOTE=13 +val SCE_ASCIIDOC_LINK=14 +val SCE_ASCIIDOC_CODEBK=15 +val SCE_ASCIIDOC_PASSBK=16 +val SCE_ASCIIDOC_COMMENT=17 +val SCE_ASCIIDOC_COMMENTBK=18 +val SCE_ASCIIDOC_LITERAL=19 +val SCE_ASCIIDOC_LITERALBK=20 +val SCE_ASCIIDOC_ATTRIB=21 +val SCE_ASCIIDOC_ATTRIBVAL=22 +val SCE_ASCIIDOC_MACRO=23 +# Lexical states for SCLEX_GDSCRIPT +lex GDScript=SCLEX_GDSCRIPT SCE_GD_ +val SCE_GD_DEFAULT=0 +val SCE_GD_COMMENTLINE=1 +val SCE_GD_NUMBER=2 +val SCE_GD_STRING=3 +val SCE_GD_CHARACTER=4 +val SCE_GD_WORD=5 +val SCE_GD_TRIPLE=6 +val SCE_GD_TRIPLEDOUBLE=7 +val SCE_GD_CLASSNAME=8 +val SCE_GD_FUNCNAME=9 +val SCE_GD_OPERATOR=10 +val SCE_GD_IDENTIFIER=11 +val SCE_GD_COMMENTBLOCK=12 +val SCE_GD_STRINGEOL=13 +val SCE_GD_WORD2=14 +val SCE_GD_ANNOTATION=15 +val SCE_GD_NODEPATH=16 +# Lexical states for SCLEX_TOML +lex TOML=SCLEX_TOML SCE_TOML_ +val SCE_TOML_DEFAULT=0 +val SCE_TOML_COMMENT=1 +val SCE_TOML_IDENTIFIER=2 +val SCE_TOML_KEYWORD=3 +val SCE_TOML_NUMBER=4 +val SCE_TOML_TABLE=5 +val SCE_TOML_KEY=6 +val SCE_TOML_ERROR=7 +val SCE_TOML_OPERATOR=8 +val SCE_TOML_STRING_SQ=9 +val SCE_TOML_STRING_DQ=10 +val SCE_TOML_TRIPLE_STRING_SQ=11 +val SCE_TOML_TRIPLE_STRING_DQ=12 +val SCE_TOML_ESCAPECHAR=13 +val SCE_TOML_DATETIME=14 diff --git a/src/lexilla/include/Lexilla.h b/src/lexilla/include/Lexilla.h new file mode 100644 index 000000000..9d23eb5df --- /dev/null +++ b/src/lexilla/include/Lexilla.h @@ -0,0 +1,108 @@ +// Lexilla lexer library +/** @file Lexilla.h + ** Lexilla definitions for dynamic and static linking. + ** For C++, more features and type safety are available with the LexillaAccess module. + **/ +// Copyright 2020 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef LEXILLA_H +#define LEXILLA_H + +// Define the default Lexilla shared library name for each platform +#if defined(_WIN32) +#define LEXILLA_LIB "lexilla" +#define LEXILLA_EXTENSION ".dll" +#else +#define LEXILLA_LIB "liblexilla" +#if defined(__APPLE__) +#define LEXILLA_EXTENSION ".dylib" +#else +#define LEXILLA_EXTENSION ".so" +#endif +#endif + +// On Win32 use the stdcall calling convention otherwise use the standard calling convention +#if defined(_WIN32) +#define LEXILLA_CALL __stdcall +#else +#define LEXILLA_CALL +#endif + +#if defined(__OBJC2__) +// Objective C(++) treats '[' as a message expression. +#define DEPRECATE_DEFINITION +#elif defined(__cplusplus) +#define DEPRECATE_DEFINITION [[deprecated]] +#elif defined(__GNUC__) || defined(__clang__) +#define DEPRECATE_DEFINITION __attribute__((deprecated)) +#else +// MSVC __declspec(deprecated) has different positioning rules to GCC so define to nothing +#define DEPRECATE_DEFINITION +#endif + +#if defined(__cplusplus) +// Must have already included ILexer.h to have Scintilla::ILexer5 defined. +using Scintilla::ILexer5; +#else +typedef void ILexer5; +#endif + +typedef ILexer5 *(*LexerFactoryFunction)(void); + +#if defined(__cplusplus) +namespace Lexilla { +#endif + +typedef int (LEXILLA_CALL *GetLexerCountFn)(void); +typedef void (LEXILLA_CALL *GetLexerNameFn)(unsigned int Index, char *name, int buflength); +typedef LexerFactoryFunction(LEXILLA_CALL *GetLexerFactoryFn)(unsigned int Index); +typedef ILexer5*(LEXILLA_CALL *CreateLexerFn)(const char *name); +DEPRECATE_DEFINITION typedef const char *(LEXILLA_CALL *LexerNameFromIDFn)(int identifier); +typedef const char *(LEXILLA_CALL *GetLibraryPropertyNamesFn)(void); +typedef void(LEXILLA_CALL *SetLibraryPropertyFn)(const char *key, const char *value); +typedef const char *(LEXILLA_CALL *GetNameSpaceFn)(void); + +#if defined(__cplusplus) +} +#endif + +#define LEXILLA_NAMESPACE_SEPARATOR '.' + +#define LEXILLA_GETLEXERCOUNT "GetLexerCount" +#define LEXILLA_GETLEXERNAME "GetLexerName" +#define LEXILLA_GETLEXERFACTORY "GetLexerFactory" +#define LEXILLA_CREATELEXER "CreateLexer" +#define LEXILLA_LEXERNAMEFROMID "LexerNameFromID" +#define LEXILLA_GETLIBRARYPROPERTYNAMES "GetLibraryPropertyNames" +#define LEXILLA_SETLIBRARYPROPERTY "SetLibraryProperty" +#define LEXILLA_GETNAMESPACE "GetNameSpace" + +// Static linking prototypes + +#if defined(__cplusplus) +extern "C" { +#endif + +ILexer5 * LEXILLA_CALL CreateLexer(const char *name); +int LEXILLA_CALL GetLexerCount(void); +void LEXILLA_CALL GetLexerName(unsigned int index, char *name, int buflength); +LexerFactoryFunction LEXILLA_CALL GetLexerFactory(unsigned int index); +DEPRECATE_DEFINITION const char *LEXILLA_CALL LexerNameFromID(int identifier); +const char * LEXILLA_CALL GetLibraryPropertyNames(void); +void LEXILLA_CALL SetLibraryProperty(const char *key, const char *value); +const char *LEXILLA_CALL GetNameSpace(void); + +#if defined(__cplusplus) +} +#endif + +#if defined(__cplusplus) +namespace Lexilla { + class LexerModule; +} +// Add a static lexer (in the same binary) to Lexilla's list +void AddStaticLexerModule(const Lexilla::LexerModule *plm); +#endif + +#endif diff --git a/src/lexilla/include/SciLexer.h b/src/lexilla/include/SciLexer.h new file mode 100644 index 000000000..ef993d1ce --- /dev/null +++ b/src/lexilla/include/SciLexer.h @@ -0,0 +1,2079 @@ +/* Scintilla source code edit control */ +/** @file SciLexer.h + ** Interface to the added lexer functions in the SciLexer version of the edit control. + **/ +/* Copyright 1998-2002 by Neil Hodgson + * The License.txt file describes the conditions under which this software may be distributed. */ + +/* Most of this file is automatically generated from the Scintilla.iface interface definition + * file which contains any comments about the definitions. HFacer.py does the generation. */ + +#ifndef SCILEXER_H +#define SCILEXER_H + +/* SciLexer features - not in standard Scintilla */ + +/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */ +#define SCLEX_CONTAINER 0 +#define SCLEX_NULL 1 +#define SCLEX_PYTHON 2 +#define SCLEX_CPP 3 +#define SCLEX_HTML 4 +#define SCLEX_XML 5 +#define SCLEX_PERL 6 +#define SCLEX_SQL 7 +#define SCLEX_VB 8 +#define SCLEX_PROPERTIES 9 +#define SCLEX_ERRORLIST 10 +#define SCLEX_MAKEFILE 11 +#define SCLEX_BATCH 12 +#define SCLEX_XCODE 13 +#define SCLEX_LATEX 14 +#define SCLEX_LUA 15 +#define SCLEX_DIFF 16 +#define SCLEX_CONF 17 +#define SCLEX_PASCAL 18 +#define SCLEX_AVE 19 +#define SCLEX_ADA 20 +#define SCLEX_LISP 21 +#define SCLEX_RUBY 22 +#define SCLEX_EIFFEL 23 +#define SCLEX_EIFFELKW 24 +#define SCLEX_TCL 25 +#define SCLEX_NNCRONTAB 26 +#define SCLEX_BULLANT 27 +#define SCLEX_VBSCRIPT 28 +#define SCLEX_BAAN 31 +#define SCLEX_MATLAB 32 +#define SCLEX_SCRIPTOL 33 +#define SCLEX_ASM 34 +#define SCLEX_CPPNOCASE 35 +#define SCLEX_FORTRAN 36 +#define SCLEX_F77 37 +#define SCLEX_CSS 38 +#define SCLEX_POV 39 +#define SCLEX_LOUT 40 +#define SCLEX_ESCRIPT 41 +#define SCLEX_PS 42 +#define SCLEX_NSIS 43 +#define SCLEX_MMIXAL 44 +#define SCLEX_CLW 45 +#define SCLEX_CLWNOCASE 46 +#define SCLEX_LOT 47 +#define SCLEX_YAML 48 +#define SCLEX_TEX 49 +#define SCLEX_METAPOST 50 +#define SCLEX_POWERBASIC 51 +#define SCLEX_FORTH 52 +#define SCLEX_ERLANG 53 +#define SCLEX_OCTAVE 54 +#define SCLEX_MSSQL 55 +#define SCLEX_VERILOG 56 +#define SCLEX_KIX 57 +#define SCLEX_GUI4CLI 58 +#define SCLEX_SPECMAN 59 +#define SCLEX_AU3 60 +#define SCLEX_APDL 61 +#define SCLEX_BASH 62 +#define SCLEX_ASN1 63 +#define SCLEX_VHDL 64 +#define SCLEX_CAML 65 +#define SCLEX_BLITZBASIC 66 +#define SCLEX_PUREBASIC 67 +#define SCLEX_HASKELL 68 +#define SCLEX_PHPSCRIPT 69 +#define SCLEX_TADS3 70 +#define SCLEX_REBOL 71 +#define SCLEX_SMALLTALK 72 +#define SCLEX_FLAGSHIP 73 +#define SCLEX_CSOUND 74 +#define SCLEX_FREEBASIC 75 +#define SCLEX_INNOSETUP 76 +#define SCLEX_OPAL 77 +#define SCLEX_SPICE 78 +#define SCLEX_D 79 +#define SCLEX_CMAKE 80 +#define SCLEX_GAP 81 +#define SCLEX_PLM 82 +#define SCLEX_PROGRESS 83 +#define SCLEX_ABAQUS 84 +#define SCLEX_ASYMPTOTE 85 +#define SCLEX_R 86 +#define SCLEX_MAGIK 87 +#define SCLEX_POWERSHELL 88 +#define SCLEX_MYSQL 89 +#define SCLEX_PO 90 +#define SCLEX_TAL 91 +#define SCLEX_COBOL 92 +#define SCLEX_TACL 93 +#define SCLEX_SORCUS 94 +#define SCLEX_POWERPRO 95 +#define SCLEX_NIMROD 96 +#define SCLEX_SML 97 +#define SCLEX_MARKDOWN 98 +#define SCLEX_TXT2TAGS 99 +#define SCLEX_A68K 100 +#define SCLEX_MODULA 101 +#define SCLEX_COFFEESCRIPT 102 +#define SCLEX_TCMD 103 +#define SCLEX_AVS 104 +#define SCLEX_ECL 105 +#define SCLEX_OSCRIPT 106 +#define SCLEX_VISUALPROLOG 107 +#define SCLEX_LITERATEHASKELL 108 +#define SCLEX_STTXT 109 +#define SCLEX_KVIRC 110 +#define SCLEX_RUST 111 +#define SCLEX_DMAP 112 +#define SCLEX_AS 113 +#define SCLEX_DMIS 114 +#define SCLEX_REGISTRY 115 +#define SCLEX_BIBTEX 116 +#define SCLEX_SREC 117 +#define SCLEX_IHEX 118 +#define SCLEX_TEHEX 119 +#define SCLEX_JSON 120 +#define SCLEX_EDIFACT 121 +#define SCLEX_INDENT 122 +#define SCLEX_MAXIMA 123 +#define SCLEX_STATA 124 +#define SCLEX_SAS 125 +#define SCLEX_NIM 126 +#define SCLEX_CIL 127 +#define SCLEX_X12 128 +#define SCLEX_DATAFLEX 129 +#define SCLEX_HOLLYWOOD 130 +#define SCLEX_RAKU 131 +#define SCLEX_FSHARP 132 +#define SCLEX_JULIA 133 +#define SCLEX_ASCIIDOC 134 +#define SCLEX_GDSCRIPT 135 +#define SCLEX_TOML 136 +#define SCLEX_AUTOMATIC 1000 +#define SCE_P_DEFAULT 0 +#define SCE_P_COMMENTLINE 1 +#define SCE_P_NUMBER 2 +#define SCE_P_STRING 3 +#define SCE_P_CHARACTER 4 +#define SCE_P_WORD 5 +#define SCE_P_TRIPLE 6 +#define SCE_P_TRIPLEDOUBLE 7 +#define SCE_P_CLASSNAME 8 +#define SCE_P_DEFNAME 9 +#define SCE_P_OPERATOR 10 +#define SCE_P_IDENTIFIER 11 +#define SCE_P_COMMENTBLOCK 12 +#define SCE_P_STRINGEOL 13 +#define SCE_P_WORD2 14 +#define SCE_P_DECORATOR 15 +#define SCE_P_FSTRING 16 +#define SCE_P_FCHARACTER 17 +#define SCE_P_FTRIPLE 18 +#define SCE_P_FTRIPLEDOUBLE 19 +#define SCE_P_ATTRIBUTE 20 +#define SCE_C_DEFAULT 0 +#define SCE_C_COMMENT 1 +#define SCE_C_COMMENTLINE 2 +#define SCE_C_COMMENTDOC 3 +#define SCE_C_NUMBER 4 +#define SCE_C_WORD 5 +#define SCE_C_STRING 6 +#define SCE_C_CHARACTER 7 +#define SCE_C_UUID 8 +#define SCE_C_PREPROCESSOR 9 +#define SCE_C_OPERATOR 10 +#define SCE_C_IDENTIFIER 11 +#define SCE_C_STRINGEOL 12 +#define SCE_C_VERBATIM 13 +#define SCE_C_REGEX 14 +#define SCE_C_COMMENTLINEDOC 15 +#define SCE_C_WORD2 16 +#define SCE_C_COMMENTDOCKEYWORD 17 +#define SCE_C_COMMENTDOCKEYWORDERROR 18 +#define SCE_C_GLOBALCLASS 19 +#define SCE_C_STRINGRAW 20 +#define SCE_C_TRIPLEVERBATIM 21 +#define SCE_C_HASHQUOTEDSTRING 22 +#define SCE_C_PREPROCESSORCOMMENT 23 +#define SCE_C_PREPROCESSORCOMMENTDOC 24 +#define SCE_C_USERLITERAL 25 +#define SCE_C_TASKMARKER 26 +#define SCE_C_ESCAPESEQUENCE 27 +#define SCE_D_DEFAULT 0 +#define SCE_D_COMMENT 1 +#define SCE_D_COMMENTLINE 2 +#define SCE_D_COMMENTDOC 3 +#define SCE_D_COMMENTNESTED 4 +#define SCE_D_NUMBER 5 +#define SCE_D_WORD 6 +#define SCE_D_WORD2 7 +#define SCE_D_WORD3 8 +#define SCE_D_TYPEDEF 9 +#define SCE_D_STRING 10 +#define SCE_D_STRINGEOL 11 +#define SCE_D_CHARACTER 12 +#define SCE_D_OPERATOR 13 +#define SCE_D_IDENTIFIER 14 +#define SCE_D_COMMENTLINEDOC 15 +#define SCE_D_COMMENTDOCKEYWORD 16 +#define SCE_D_COMMENTDOCKEYWORDERROR 17 +#define SCE_D_STRINGB 18 +#define SCE_D_STRINGR 19 +#define SCE_D_WORD5 20 +#define SCE_D_WORD6 21 +#define SCE_D_WORD7 22 +#define SCE_TCL_DEFAULT 0 +#define SCE_TCL_COMMENT 1 +#define SCE_TCL_COMMENTLINE 2 +#define SCE_TCL_NUMBER 3 +#define SCE_TCL_WORD_IN_QUOTE 4 +#define SCE_TCL_IN_QUOTE 5 +#define SCE_TCL_OPERATOR 6 +#define SCE_TCL_IDENTIFIER 7 +#define SCE_TCL_SUBSTITUTION 8 +#define SCE_TCL_SUB_BRACE 9 +#define SCE_TCL_MODIFIER 10 +#define SCE_TCL_EXPAND 11 +#define SCE_TCL_WORD 12 +#define SCE_TCL_WORD2 13 +#define SCE_TCL_WORD3 14 +#define SCE_TCL_WORD4 15 +#define SCE_TCL_WORD5 16 +#define SCE_TCL_WORD6 17 +#define SCE_TCL_WORD7 18 +#define SCE_TCL_WORD8 19 +#define SCE_TCL_COMMENT_BOX 20 +#define SCE_TCL_BLOCK_COMMENT 21 +#define SCE_H_DEFAULT 0 +#define SCE_H_TAG 1 +#define SCE_H_TAGUNKNOWN 2 +#define SCE_H_ATTRIBUTE 3 +#define SCE_H_ATTRIBUTEUNKNOWN 4 +#define SCE_H_NUMBER 5 +#define SCE_H_DOUBLESTRING 6 +#define SCE_H_SINGLESTRING 7 +#define SCE_H_OTHER 8 +#define SCE_H_COMMENT 9 +#define SCE_H_ENTITY 10 +#define SCE_H_TAGEND 11 +#define SCE_H_XMLSTART 12 +#define SCE_H_XMLEND 13 +#define SCE_H_SCRIPT 14 +#define SCE_H_ASP 15 +#define SCE_H_ASPAT 16 +#define SCE_H_CDATA 17 +#define SCE_H_QUESTION 18 +#define SCE_H_VALUE 19 +#define SCE_H_XCCOMMENT 20 +#define SCE_H_SGML_DEFAULT 21 +#define SCE_H_SGML_COMMAND 22 +#define SCE_H_SGML_1ST_PARAM 23 +#define SCE_H_SGML_DOUBLESTRING 24 +#define SCE_H_SGML_SIMPLESTRING 25 +#define SCE_H_SGML_ERROR 26 +#define SCE_H_SGML_SPECIAL 27 +#define SCE_H_SGML_ENTITY 28 +#define SCE_H_SGML_COMMENT 29 +#define SCE_H_SGML_1ST_PARAM_COMMENT 30 +#define SCE_H_SGML_BLOCK_DEFAULT 31 +#define SCE_HJ_START 40 +#define SCE_HJ_DEFAULT 41 +#define SCE_HJ_COMMENT 42 +#define SCE_HJ_COMMENTLINE 43 +#define SCE_HJ_COMMENTDOC 44 +#define SCE_HJ_NUMBER 45 +#define SCE_HJ_WORD 46 +#define SCE_HJ_KEYWORD 47 +#define SCE_HJ_DOUBLESTRING 48 +#define SCE_HJ_SINGLESTRING 49 +#define SCE_HJ_SYMBOLS 50 +#define SCE_HJ_STRINGEOL 51 +#define SCE_HJ_REGEX 52 +#define SCE_HJA_START 55 +#define SCE_HJA_DEFAULT 56 +#define SCE_HJA_COMMENT 57 +#define SCE_HJA_COMMENTLINE 58 +#define SCE_HJA_COMMENTDOC 59 +#define SCE_HJA_NUMBER 60 +#define SCE_HJA_WORD 61 +#define SCE_HJA_KEYWORD 62 +#define SCE_HJA_DOUBLESTRING 63 +#define SCE_HJA_SINGLESTRING 64 +#define SCE_HJA_SYMBOLS 65 +#define SCE_HJA_STRINGEOL 66 +#define SCE_HJA_REGEX 67 +#define SCE_HB_START 70 +#define SCE_HB_DEFAULT 71 +#define SCE_HB_COMMENTLINE 72 +#define SCE_HB_NUMBER 73 +#define SCE_HB_WORD 74 +#define SCE_HB_STRING 75 +#define SCE_HB_IDENTIFIER 76 +#define SCE_HB_STRINGEOL 77 +#define SCE_HBA_START 80 +#define SCE_HBA_DEFAULT 81 +#define SCE_HBA_COMMENTLINE 82 +#define SCE_HBA_NUMBER 83 +#define SCE_HBA_WORD 84 +#define SCE_HBA_STRING 85 +#define SCE_HBA_IDENTIFIER 86 +#define SCE_HBA_STRINGEOL 87 +#define SCE_HP_START 90 +#define SCE_HP_DEFAULT 91 +#define SCE_HP_COMMENTLINE 92 +#define SCE_HP_NUMBER 93 +#define SCE_HP_STRING 94 +#define SCE_HP_CHARACTER 95 +#define SCE_HP_WORD 96 +#define SCE_HP_TRIPLE 97 +#define SCE_HP_TRIPLEDOUBLE 98 +#define SCE_HP_CLASSNAME 99 +#define SCE_HP_DEFNAME 100 +#define SCE_HP_OPERATOR 101 +#define SCE_HP_IDENTIFIER 102 +#define SCE_HPHP_COMPLEX_VARIABLE 104 +#define SCE_HPA_START 105 +#define SCE_HPA_DEFAULT 106 +#define SCE_HPA_COMMENTLINE 107 +#define SCE_HPA_NUMBER 108 +#define SCE_HPA_STRING 109 +#define SCE_HPA_CHARACTER 110 +#define SCE_HPA_WORD 111 +#define SCE_HPA_TRIPLE 112 +#define SCE_HPA_TRIPLEDOUBLE 113 +#define SCE_HPA_CLASSNAME 114 +#define SCE_HPA_DEFNAME 115 +#define SCE_HPA_OPERATOR 116 +#define SCE_HPA_IDENTIFIER 117 +#define SCE_HPHP_DEFAULT 118 +#define SCE_HPHP_HSTRING 119 +#define SCE_HPHP_SIMPLESTRING 120 +#define SCE_HPHP_WORD 121 +#define SCE_HPHP_NUMBER 122 +#define SCE_HPHP_VARIABLE 123 +#define SCE_HPHP_COMMENT 124 +#define SCE_HPHP_COMMENTLINE 125 +#define SCE_HPHP_HSTRING_VARIABLE 126 +#define SCE_HPHP_OPERATOR 127 +#define SCE_PL_DEFAULT 0 +#define SCE_PL_ERROR 1 +#define SCE_PL_COMMENTLINE 2 +#define SCE_PL_POD 3 +#define SCE_PL_NUMBER 4 +#define SCE_PL_WORD 5 +#define SCE_PL_STRING 6 +#define SCE_PL_CHARACTER 7 +#define SCE_PL_PUNCTUATION 8 +#define SCE_PL_PREPROCESSOR 9 +#define SCE_PL_OPERATOR 10 +#define SCE_PL_IDENTIFIER 11 +#define SCE_PL_SCALAR 12 +#define SCE_PL_ARRAY 13 +#define SCE_PL_HASH 14 +#define SCE_PL_SYMBOLTABLE 15 +#define SCE_PL_VARIABLE_INDEXER 16 +#define SCE_PL_REGEX 17 +#define SCE_PL_REGSUBST 18 +#define SCE_PL_LONGQUOTE 19 +#define SCE_PL_BACKTICKS 20 +#define SCE_PL_DATASECTION 21 +#define SCE_PL_HERE_DELIM 22 +#define SCE_PL_HERE_Q 23 +#define SCE_PL_HERE_QQ 24 +#define SCE_PL_HERE_QX 25 +#define SCE_PL_STRING_Q 26 +#define SCE_PL_STRING_QQ 27 +#define SCE_PL_STRING_QX 28 +#define SCE_PL_STRING_QR 29 +#define SCE_PL_STRING_QW 30 +#define SCE_PL_POD_VERB 31 +#define SCE_PL_SUB_PROTOTYPE 40 +#define SCE_PL_FORMAT_IDENT 41 +#define SCE_PL_FORMAT 42 +#define SCE_PL_STRING_VAR 43 +#define SCE_PL_XLAT 44 +#define SCE_PL_REGEX_VAR 54 +#define SCE_PL_REGSUBST_VAR 55 +#define SCE_PL_BACKTICKS_VAR 57 +#define SCE_PL_HERE_QQ_VAR 61 +#define SCE_PL_HERE_QX_VAR 62 +#define SCE_PL_STRING_QQ_VAR 64 +#define SCE_PL_STRING_QX_VAR 65 +#define SCE_PL_STRING_QR_VAR 66 +#define SCE_RB_DEFAULT 0 +#define SCE_RB_ERROR 1 +#define SCE_RB_COMMENTLINE 2 +#define SCE_RB_POD 3 +#define SCE_RB_NUMBER 4 +#define SCE_RB_WORD 5 +#define SCE_RB_STRING 6 +#define SCE_RB_CHARACTER 7 +#define SCE_RB_CLASSNAME 8 +#define SCE_RB_DEFNAME 9 +#define SCE_RB_OPERATOR 10 +#define SCE_RB_IDENTIFIER 11 +#define SCE_RB_REGEX 12 +#define SCE_RB_GLOBAL 13 +#define SCE_RB_SYMBOL 14 +#define SCE_RB_MODULE_NAME 15 +#define SCE_RB_INSTANCE_VAR 16 +#define SCE_RB_CLASS_VAR 17 +#define SCE_RB_BACKTICKS 18 +#define SCE_RB_DATASECTION 19 +#define SCE_RB_HERE_DELIM 20 +#define SCE_RB_HERE_Q 21 +#define SCE_RB_HERE_QQ 22 +#define SCE_RB_HERE_QX 23 +#define SCE_RB_STRING_Q 24 +#define SCE_RB_STRING_QQ 25 +#define SCE_RB_STRING_QX 26 +#define SCE_RB_STRING_QR 27 +#define SCE_RB_STRING_QW 28 +#define SCE_RB_WORD_DEMOTED 29 +#define SCE_RB_STDIN 30 +#define SCE_RB_STDOUT 31 +#define SCE_RB_STDERR 40 +#define SCE_RB_STRING_W 41 +#define SCE_RB_STRING_I 42 +#define SCE_RB_STRING_QI 43 +#define SCE_RB_STRING_QS 44 +#define SCE_RB_UPPER_BOUND 45 +#define SCE_B_DEFAULT 0 +#define SCE_B_COMMENT 1 +#define SCE_B_NUMBER 2 +#define SCE_B_KEYWORD 3 +#define SCE_B_STRING 4 +#define SCE_B_PREPROCESSOR 5 +#define SCE_B_OPERATOR 6 +#define SCE_B_IDENTIFIER 7 +#define SCE_B_DATE 8 +#define SCE_B_STRINGEOL 9 +#define SCE_B_KEYWORD2 10 +#define SCE_B_KEYWORD3 11 +#define SCE_B_KEYWORD4 12 +#define SCE_B_CONSTANT 13 +#define SCE_B_ASM 14 +#define SCE_B_LABEL 15 +#define SCE_B_ERROR 16 +#define SCE_B_HEXNUMBER 17 +#define SCE_B_BINNUMBER 18 +#define SCE_B_COMMENTBLOCK 19 +#define SCE_B_DOCLINE 20 +#define SCE_B_DOCBLOCK 21 +#define SCE_B_DOCKEYWORD 22 +#define SCE_PROPS_DEFAULT 0 +#define SCE_PROPS_COMMENT 1 +#define SCE_PROPS_SECTION 2 +#define SCE_PROPS_ASSIGNMENT 3 +#define SCE_PROPS_DEFVAL 4 +#define SCE_PROPS_KEY 5 +#define SCE_L_DEFAULT 0 +#define SCE_L_COMMAND 1 +#define SCE_L_TAG 2 +#define SCE_L_MATH 3 +#define SCE_L_COMMENT 4 +#define SCE_L_TAG2 5 +#define SCE_L_MATH2 6 +#define SCE_L_COMMENT2 7 +#define SCE_L_VERBATIM 8 +#define SCE_L_SHORTCMD 9 +#define SCE_L_SPECIAL 10 +#define SCE_L_CMDOPT 11 +#define SCE_L_ERROR 12 +#define SCE_LUA_DEFAULT 0 +#define SCE_LUA_COMMENT 1 +#define SCE_LUA_COMMENTLINE 2 +#define SCE_LUA_COMMENTDOC 3 +#define SCE_LUA_NUMBER 4 +#define SCE_LUA_WORD 5 +#define SCE_LUA_STRING 6 +#define SCE_LUA_CHARACTER 7 +#define SCE_LUA_LITERALSTRING 8 +#define SCE_LUA_PREPROCESSOR 9 +#define SCE_LUA_OPERATOR 10 +#define SCE_LUA_IDENTIFIER 11 +#define SCE_LUA_STRINGEOL 12 +#define SCE_LUA_WORD2 13 +#define SCE_LUA_WORD3 14 +#define SCE_LUA_WORD4 15 +#define SCE_LUA_WORD5 16 +#define SCE_LUA_WORD6 17 +#define SCE_LUA_WORD7 18 +#define SCE_LUA_WORD8 19 +#define SCE_LUA_LABEL 20 +#define SCE_ERR_DEFAULT 0 +#define SCE_ERR_PYTHON 1 +#define SCE_ERR_GCC 2 +#define SCE_ERR_MS 3 +#define SCE_ERR_CMD 4 +#define SCE_ERR_BORLAND 5 +#define SCE_ERR_PERL 6 +#define SCE_ERR_NET 7 +#define SCE_ERR_LUA 8 +#define SCE_ERR_CTAG 9 +#define SCE_ERR_DIFF_CHANGED 10 +#define SCE_ERR_DIFF_ADDITION 11 +#define SCE_ERR_DIFF_DELETION 12 +#define SCE_ERR_DIFF_MESSAGE 13 +#define SCE_ERR_PHP 14 +#define SCE_ERR_ELF 15 +#define SCE_ERR_IFC 16 +#define SCE_ERR_IFORT 17 +#define SCE_ERR_ABSF 18 +#define SCE_ERR_TIDY 19 +#define SCE_ERR_JAVA_STACK 20 +#define SCE_ERR_VALUE 21 +#define SCE_ERR_GCC_INCLUDED_FROM 22 +#define SCE_ERR_ESCSEQ 23 +#define SCE_ERR_ESCSEQ_UNKNOWN 24 +#define SCE_ERR_GCC_EXCERPT 25 +#define SCE_ERR_BASH 26 +#define SCE_ERR_ES_BLACK 40 +#define SCE_ERR_ES_RED 41 +#define SCE_ERR_ES_GREEN 42 +#define SCE_ERR_ES_BROWN 43 +#define SCE_ERR_ES_BLUE 44 +#define SCE_ERR_ES_MAGENTA 45 +#define SCE_ERR_ES_CYAN 46 +#define SCE_ERR_ES_GRAY 47 +#define SCE_ERR_ES_DARK_GRAY 48 +#define SCE_ERR_ES_BRIGHT_RED 49 +#define SCE_ERR_ES_BRIGHT_GREEN 50 +#define SCE_ERR_ES_YELLOW 51 +#define SCE_ERR_ES_BRIGHT_BLUE 52 +#define SCE_ERR_ES_BRIGHT_MAGENTA 53 +#define SCE_ERR_ES_BRIGHT_CYAN 54 +#define SCE_ERR_ES_WHITE 55 +#define SCE_BAT_DEFAULT 0 +#define SCE_BAT_COMMENT 1 +#define SCE_BAT_WORD 2 +#define SCE_BAT_LABEL 3 +#define SCE_BAT_HIDE 4 +#define SCE_BAT_COMMAND 5 +#define SCE_BAT_IDENTIFIER 6 +#define SCE_BAT_OPERATOR 7 +#define SCE_BAT_AFTER_LABEL 8 +#define SCE_TCMD_DEFAULT 0 +#define SCE_TCMD_COMMENT 1 +#define SCE_TCMD_WORD 2 +#define SCE_TCMD_LABEL 3 +#define SCE_TCMD_HIDE 4 +#define SCE_TCMD_COMMAND 5 +#define SCE_TCMD_IDENTIFIER 6 +#define SCE_TCMD_OPERATOR 7 +#define SCE_TCMD_ENVIRONMENT 8 +#define SCE_TCMD_EXPANSION 9 +#define SCE_TCMD_CLABEL 10 +#define SCE_MAKE_DEFAULT 0 +#define SCE_MAKE_COMMENT 1 +#define SCE_MAKE_PREPROCESSOR 2 +#define SCE_MAKE_IDENTIFIER 3 +#define SCE_MAKE_OPERATOR 4 +#define SCE_MAKE_TARGET 5 +#define SCE_MAKE_IDEOL 9 +#define SCE_DIFF_DEFAULT 0 +#define SCE_DIFF_COMMENT 1 +#define SCE_DIFF_COMMAND 2 +#define SCE_DIFF_HEADER 3 +#define SCE_DIFF_POSITION 4 +#define SCE_DIFF_DELETED 5 +#define SCE_DIFF_ADDED 6 +#define SCE_DIFF_CHANGED 7 +#define SCE_DIFF_PATCH_ADD 8 +#define SCE_DIFF_PATCH_DELETE 9 +#define SCE_DIFF_REMOVED_PATCH_ADD 10 +#define SCE_DIFF_REMOVED_PATCH_DELETE 11 +#define SCE_CONF_DEFAULT 0 +#define SCE_CONF_COMMENT 1 +#define SCE_CONF_NUMBER 2 +#define SCE_CONF_IDENTIFIER 3 +#define SCE_CONF_EXTENSION 4 +#define SCE_CONF_PARAMETER 5 +#define SCE_CONF_STRING 6 +#define SCE_CONF_OPERATOR 7 +#define SCE_CONF_IP 8 +#define SCE_CONF_DIRECTIVE 9 +#define SCE_AVE_DEFAULT 0 +#define SCE_AVE_COMMENT 1 +#define SCE_AVE_NUMBER 2 +#define SCE_AVE_WORD 3 +#define SCE_AVE_STRING 6 +#define SCE_AVE_ENUM 7 +#define SCE_AVE_STRINGEOL 8 +#define SCE_AVE_IDENTIFIER 9 +#define SCE_AVE_OPERATOR 10 +#define SCE_AVE_WORD1 11 +#define SCE_AVE_WORD2 12 +#define SCE_AVE_WORD3 13 +#define SCE_AVE_WORD4 14 +#define SCE_AVE_WORD5 15 +#define SCE_AVE_WORD6 16 +#define SCE_ADA_DEFAULT 0 +#define SCE_ADA_WORD 1 +#define SCE_ADA_IDENTIFIER 2 +#define SCE_ADA_NUMBER 3 +#define SCE_ADA_DELIMITER 4 +#define SCE_ADA_CHARACTER 5 +#define SCE_ADA_CHARACTEREOL 6 +#define SCE_ADA_STRING 7 +#define SCE_ADA_STRINGEOL 8 +#define SCE_ADA_LABEL 9 +#define SCE_ADA_COMMENTLINE 10 +#define SCE_ADA_ILLEGAL 11 +#define SCE_BAAN_DEFAULT 0 +#define SCE_BAAN_COMMENT 1 +#define SCE_BAAN_COMMENTDOC 2 +#define SCE_BAAN_NUMBER 3 +#define SCE_BAAN_WORD 4 +#define SCE_BAAN_STRING 5 +#define SCE_BAAN_PREPROCESSOR 6 +#define SCE_BAAN_OPERATOR 7 +#define SCE_BAAN_IDENTIFIER 8 +#define SCE_BAAN_STRINGEOL 9 +#define SCE_BAAN_WORD2 10 +#define SCE_BAAN_WORD3 11 +#define SCE_BAAN_WORD4 12 +#define SCE_BAAN_WORD5 13 +#define SCE_BAAN_WORD6 14 +#define SCE_BAAN_WORD7 15 +#define SCE_BAAN_WORD8 16 +#define SCE_BAAN_WORD9 17 +#define SCE_BAAN_TABLEDEF 18 +#define SCE_BAAN_TABLESQL 19 +#define SCE_BAAN_FUNCTION 20 +#define SCE_BAAN_DOMDEF 21 +#define SCE_BAAN_FUNCDEF 22 +#define SCE_BAAN_OBJECTDEF 23 +#define SCE_BAAN_DEFINEDEF 24 +#define SCE_LISP_DEFAULT 0 +#define SCE_LISP_COMMENT 1 +#define SCE_LISP_NUMBER 2 +#define SCE_LISP_KEYWORD 3 +#define SCE_LISP_KEYWORD_KW 4 +#define SCE_LISP_SYMBOL 5 +#define SCE_LISP_STRING 6 +#define SCE_LISP_STRINGEOL 8 +#define SCE_LISP_IDENTIFIER 9 +#define SCE_LISP_OPERATOR 10 +#define SCE_LISP_SPECIAL 11 +#define SCE_LISP_MULTI_COMMENT 12 +#define SCE_EIFFEL_DEFAULT 0 +#define SCE_EIFFEL_COMMENTLINE 1 +#define SCE_EIFFEL_NUMBER 2 +#define SCE_EIFFEL_WORD 3 +#define SCE_EIFFEL_STRING 4 +#define SCE_EIFFEL_CHARACTER 5 +#define SCE_EIFFEL_OPERATOR 6 +#define SCE_EIFFEL_IDENTIFIER 7 +#define SCE_EIFFEL_STRINGEOL 8 +#define SCE_NNCRONTAB_DEFAULT 0 +#define SCE_NNCRONTAB_COMMENT 1 +#define SCE_NNCRONTAB_TASK 2 +#define SCE_NNCRONTAB_SECTION 3 +#define SCE_NNCRONTAB_KEYWORD 4 +#define SCE_NNCRONTAB_MODIFIER 5 +#define SCE_NNCRONTAB_ASTERISK 6 +#define SCE_NNCRONTAB_NUMBER 7 +#define SCE_NNCRONTAB_STRING 8 +#define SCE_NNCRONTAB_ENVIRONMENT 9 +#define SCE_NNCRONTAB_IDENTIFIER 10 +#define SCE_FORTH_DEFAULT 0 +#define SCE_FORTH_COMMENT 1 +#define SCE_FORTH_COMMENT_ML 2 +#define SCE_FORTH_IDENTIFIER 3 +#define SCE_FORTH_CONTROL 4 +#define SCE_FORTH_KEYWORD 5 +#define SCE_FORTH_DEFWORD 6 +#define SCE_FORTH_PREWORD1 7 +#define SCE_FORTH_PREWORD2 8 +#define SCE_FORTH_NUMBER 9 +#define SCE_FORTH_STRING 10 +#define SCE_FORTH_LOCALE 11 +#define SCE_MATLAB_DEFAULT 0 +#define SCE_MATLAB_COMMENT 1 +#define SCE_MATLAB_COMMAND 2 +#define SCE_MATLAB_NUMBER 3 +#define SCE_MATLAB_KEYWORD 4 +#define SCE_MATLAB_STRING 5 +#define SCE_MATLAB_OPERATOR 6 +#define SCE_MATLAB_IDENTIFIER 7 +#define SCE_MATLAB_DOUBLEQUOTESTRING 8 +#define SCE_MAXIMA_OPERATOR 0 +#define SCE_MAXIMA_COMMANDENDING 1 +#define SCE_MAXIMA_COMMENT 2 +#define SCE_MAXIMA_NUMBER 3 +#define SCE_MAXIMA_STRING 4 +#define SCE_MAXIMA_COMMAND 5 +#define SCE_MAXIMA_VARIABLE 6 +#define SCE_MAXIMA_UNKNOWN 7 +#define SCE_SCRIPTOL_DEFAULT 0 +#define SCE_SCRIPTOL_WHITE 1 +#define SCE_SCRIPTOL_COMMENTLINE 2 +#define SCE_SCRIPTOL_PERSISTENT 3 +#define SCE_SCRIPTOL_CSTYLE 4 +#define SCE_SCRIPTOL_COMMENTBLOCK 5 +#define SCE_SCRIPTOL_NUMBER 6 +#define SCE_SCRIPTOL_STRING 7 +#define SCE_SCRIPTOL_CHARACTER 8 +#define SCE_SCRIPTOL_STRINGEOL 9 +#define SCE_SCRIPTOL_KEYWORD 10 +#define SCE_SCRIPTOL_OPERATOR 11 +#define SCE_SCRIPTOL_IDENTIFIER 12 +#define SCE_SCRIPTOL_TRIPLE 13 +#define SCE_SCRIPTOL_CLASSNAME 14 +#define SCE_SCRIPTOL_PREPROCESSOR 15 +#define SCE_ASM_DEFAULT 0 +#define SCE_ASM_COMMENT 1 +#define SCE_ASM_NUMBER 2 +#define SCE_ASM_STRING 3 +#define SCE_ASM_OPERATOR 4 +#define SCE_ASM_IDENTIFIER 5 +#define SCE_ASM_CPUINSTRUCTION 6 +#define SCE_ASM_MATHINSTRUCTION 7 +#define SCE_ASM_REGISTER 8 +#define SCE_ASM_DIRECTIVE 9 +#define SCE_ASM_DIRECTIVEOPERAND 10 +#define SCE_ASM_COMMENTBLOCK 11 +#define SCE_ASM_CHARACTER 12 +#define SCE_ASM_STRINGEOL 13 +#define SCE_ASM_EXTINSTRUCTION 14 +#define SCE_ASM_COMMENTDIRECTIVE 15 +#define SCE_F_DEFAULT 0 +#define SCE_F_COMMENT 1 +#define SCE_F_NUMBER 2 +#define SCE_F_STRING1 3 +#define SCE_F_STRING2 4 +#define SCE_F_STRINGEOL 5 +#define SCE_F_OPERATOR 6 +#define SCE_F_IDENTIFIER 7 +#define SCE_F_WORD 8 +#define SCE_F_WORD2 9 +#define SCE_F_WORD3 10 +#define SCE_F_PREPROCESSOR 11 +#define SCE_F_OPERATOR2 12 +#define SCE_F_LABEL 13 +#define SCE_F_CONTINUATION 14 +#define SCE_CSS_DEFAULT 0 +#define SCE_CSS_TAG 1 +#define SCE_CSS_CLASS 2 +#define SCE_CSS_PSEUDOCLASS 3 +#define SCE_CSS_UNKNOWN_PSEUDOCLASS 4 +#define SCE_CSS_OPERATOR 5 +#define SCE_CSS_IDENTIFIER 6 +#define SCE_CSS_UNKNOWN_IDENTIFIER 7 +#define SCE_CSS_VALUE 8 +#define SCE_CSS_COMMENT 9 +#define SCE_CSS_ID 10 +#define SCE_CSS_IMPORTANT 11 +#define SCE_CSS_DIRECTIVE 12 +#define SCE_CSS_DOUBLESTRING 13 +#define SCE_CSS_SINGLESTRING 14 +#define SCE_CSS_IDENTIFIER2 15 +#define SCE_CSS_ATTRIBUTE 16 +#define SCE_CSS_IDENTIFIER3 17 +#define SCE_CSS_PSEUDOELEMENT 18 +#define SCE_CSS_EXTENDED_IDENTIFIER 19 +#define SCE_CSS_EXTENDED_PSEUDOCLASS 20 +#define SCE_CSS_EXTENDED_PSEUDOELEMENT 21 +#define SCE_CSS_GROUP_RULE 22 +#define SCE_CSS_VARIABLE 23 +#define SCE_POV_DEFAULT 0 +#define SCE_POV_COMMENT 1 +#define SCE_POV_COMMENTLINE 2 +#define SCE_POV_NUMBER 3 +#define SCE_POV_OPERATOR 4 +#define SCE_POV_IDENTIFIER 5 +#define SCE_POV_STRING 6 +#define SCE_POV_STRINGEOL 7 +#define SCE_POV_DIRECTIVE 8 +#define SCE_POV_BADDIRECTIVE 9 +#define SCE_POV_WORD2 10 +#define SCE_POV_WORD3 11 +#define SCE_POV_WORD4 12 +#define SCE_POV_WORD5 13 +#define SCE_POV_WORD6 14 +#define SCE_POV_WORD7 15 +#define SCE_POV_WORD8 16 +#define SCE_LOUT_DEFAULT 0 +#define SCE_LOUT_COMMENT 1 +#define SCE_LOUT_NUMBER 2 +#define SCE_LOUT_WORD 3 +#define SCE_LOUT_WORD2 4 +#define SCE_LOUT_WORD3 5 +#define SCE_LOUT_WORD4 6 +#define SCE_LOUT_STRING 7 +#define SCE_LOUT_OPERATOR 8 +#define SCE_LOUT_IDENTIFIER 9 +#define SCE_LOUT_STRINGEOL 10 +#define SCE_ESCRIPT_DEFAULT 0 +#define SCE_ESCRIPT_COMMENT 1 +#define SCE_ESCRIPT_COMMENTLINE 2 +#define SCE_ESCRIPT_COMMENTDOC 3 +#define SCE_ESCRIPT_NUMBER 4 +#define SCE_ESCRIPT_WORD 5 +#define SCE_ESCRIPT_STRING 6 +#define SCE_ESCRIPT_OPERATOR 7 +#define SCE_ESCRIPT_IDENTIFIER 8 +#define SCE_ESCRIPT_BRACE 9 +#define SCE_ESCRIPT_WORD2 10 +#define SCE_ESCRIPT_WORD3 11 +#define SCE_PS_DEFAULT 0 +#define SCE_PS_COMMENT 1 +#define SCE_PS_DSC_COMMENT 2 +#define SCE_PS_DSC_VALUE 3 +#define SCE_PS_NUMBER 4 +#define SCE_PS_NAME 5 +#define SCE_PS_KEYWORD 6 +#define SCE_PS_LITERAL 7 +#define SCE_PS_IMMEVAL 8 +#define SCE_PS_PAREN_ARRAY 9 +#define SCE_PS_PAREN_DICT 10 +#define SCE_PS_PAREN_PROC 11 +#define SCE_PS_TEXT 12 +#define SCE_PS_HEXSTRING 13 +#define SCE_PS_BASE85STRING 14 +#define SCE_PS_BADSTRINGCHAR 15 +#define SCE_NSIS_DEFAULT 0 +#define SCE_NSIS_COMMENT 1 +#define SCE_NSIS_STRINGDQ 2 +#define SCE_NSIS_STRINGLQ 3 +#define SCE_NSIS_STRINGRQ 4 +#define SCE_NSIS_FUNCTION 5 +#define SCE_NSIS_VARIABLE 6 +#define SCE_NSIS_LABEL 7 +#define SCE_NSIS_USERDEFINED 8 +#define SCE_NSIS_SECTIONDEF 9 +#define SCE_NSIS_SUBSECTIONDEF 10 +#define SCE_NSIS_IFDEFINEDEF 11 +#define SCE_NSIS_MACRODEF 12 +#define SCE_NSIS_STRINGVAR 13 +#define SCE_NSIS_NUMBER 14 +#define SCE_NSIS_SECTIONGROUP 15 +#define SCE_NSIS_PAGEEX 16 +#define SCE_NSIS_FUNCTIONDEF 17 +#define SCE_NSIS_COMMENTBOX 18 +#define SCE_MMIXAL_LEADWS 0 +#define SCE_MMIXAL_COMMENT 1 +#define SCE_MMIXAL_LABEL 2 +#define SCE_MMIXAL_OPCODE 3 +#define SCE_MMIXAL_OPCODE_PRE 4 +#define SCE_MMIXAL_OPCODE_VALID 5 +#define SCE_MMIXAL_OPCODE_UNKNOWN 6 +#define SCE_MMIXAL_OPCODE_POST 7 +#define SCE_MMIXAL_OPERANDS 8 +#define SCE_MMIXAL_NUMBER 9 +#define SCE_MMIXAL_REF 10 +#define SCE_MMIXAL_CHAR 11 +#define SCE_MMIXAL_STRING 12 +#define SCE_MMIXAL_REGISTER 13 +#define SCE_MMIXAL_HEX 14 +#define SCE_MMIXAL_OPERATOR 15 +#define SCE_MMIXAL_SYMBOL 16 +#define SCE_MMIXAL_INCLUDE 17 +#define SCE_CLW_DEFAULT 0 +#define SCE_CLW_LABEL 1 +#define SCE_CLW_COMMENT 2 +#define SCE_CLW_STRING 3 +#define SCE_CLW_USER_IDENTIFIER 4 +#define SCE_CLW_INTEGER_CONSTANT 5 +#define SCE_CLW_REAL_CONSTANT 6 +#define SCE_CLW_PICTURE_STRING 7 +#define SCE_CLW_KEYWORD 8 +#define SCE_CLW_COMPILER_DIRECTIVE 9 +#define SCE_CLW_RUNTIME_EXPRESSIONS 10 +#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 11 +#define SCE_CLW_STRUCTURE_DATA_TYPE 12 +#define SCE_CLW_ATTRIBUTE 13 +#define SCE_CLW_STANDARD_EQUATE 14 +#define SCE_CLW_ERROR 15 +#define SCE_CLW_DEPRECATED 16 +#define SCE_LOT_DEFAULT 0 +#define SCE_LOT_HEADER 1 +#define SCE_LOT_BREAK 2 +#define SCE_LOT_SET 3 +#define SCE_LOT_PASS 4 +#define SCE_LOT_FAIL 5 +#define SCE_LOT_ABORT 6 +#define SCE_YAML_DEFAULT 0 +#define SCE_YAML_COMMENT 1 +#define SCE_YAML_IDENTIFIER 2 +#define SCE_YAML_KEYWORD 3 +#define SCE_YAML_NUMBER 4 +#define SCE_YAML_REFERENCE 5 +#define SCE_YAML_DOCUMENT 6 +#define SCE_YAML_TEXT 7 +#define SCE_YAML_ERROR 8 +#define SCE_YAML_OPERATOR 9 +#define SCE_TEX_DEFAULT 0 +#define SCE_TEX_SPECIAL 1 +#define SCE_TEX_GROUP 2 +#define SCE_TEX_SYMBOL 3 +#define SCE_TEX_COMMAND 4 +#define SCE_TEX_TEXT 5 +#define SCE_METAPOST_DEFAULT 0 +#define SCE_METAPOST_SPECIAL 1 +#define SCE_METAPOST_GROUP 2 +#define SCE_METAPOST_SYMBOL 3 +#define SCE_METAPOST_COMMAND 4 +#define SCE_METAPOST_TEXT 5 +#define SCE_METAPOST_EXTRA 6 +#define SCE_ERLANG_DEFAULT 0 +#define SCE_ERLANG_COMMENT 1 +#define SCE_ERLANG_VARIABLE 2 +#define SCE_ERLANG_NUMBER 3 +#define SCE_ERLANG_KEYWORD 4 +#define SCE_ERLANG_STRING 5 +#define SCE_ERLANG_OPERATOR 6 +#define SCE_ERLANG_ATOM 7 +#define SCE_ERLANG_FUNCTION_NAME 8 +#define SCE_ERLANG_CHARACTER 9 +#define SCE_ERLANG_MACRO 10 +#define SCE_ERLANG_RECORD 11 +#define SCE_ERLANG_PREPROC 12 +#define SCE_ERLANG_NODE_NAME 13 +#define SCE_ERLANG_COMMENT_FUNCTION 14 +#define SCE_ERLANG_COMMENT_MODULE 15 +#define SCE_ERLANG_COMMENT_DOC 16 +#define SCE_ERLANG_COMMENT_DOC_MACRO 17 +#define SCE_ERLANG_ATOM_QUOTED 18 +#define SCE_ERLANG_MACRO_QUOTED 19 +#define SCE_ERLANG_RECORD_QUOTED 20 +#define SCE_ERLANG_NODE_NAME_QUOTED 21 +#define SCE_ERLANG_BIFS 22 +#define SCE_ERLANG_MODULES 23 +#define SCE_ERLANG_MODULES_ATT 24 +#define SCE_ERLANG_UNKNOWN 31 +#define SCE_JULIA_DEFAULT 0 +#define SCE_JULIA_COMMENT 1 +#define SCE_JULIA_NUMBER 2 +#define SCE_JULIA_KEYWORD1 3 +#define SCE_JULIA_KEYWORD2 4 +#define SCE_JULIA_KEYWORD3 5 +#define SCE_JULIA_CHAR 6 +#define SCE_JULIA_OPERATOR 7 +#define SCE_JULIA_BRACKET 8 +#define SCE_JULIA_IDENTIFIER 9 +#define SCE_JULIA_STRING 10 +#define SCE_JULIA_SYMBOL 11 +#define SCE_JULIA_MACRO 12 +#define SCE_JULIA_STRINGINTERP 13 +#define SCE_JULIA_DOCSTRING 14 +#define SCE_JULIA_STRINGLITERAL 15 +#define SCE_JULIA_COMMAND 16 +#define SCE_JULIA_COMMANDLITERAL 17 +#define SCE_JULIA_TYPEANNOT 18 +#define SCE_JULIA_LEXERROR 19 +#define SCE_JULIA_KEYWORD4 20 +#define SCE_JULIA_TYPEOPERATOR 21 +#define SCE_MSSQL_DEFAULT 0 +#define SCE_MSSQL_COMMENT 1 +#define SCE_MSSQL_LINE_COMMENT 2 +#define SCE_MSSQL_NUMBER 3 +#define SCE_MSSQL_STRING 4 +#define SCE_MSSQL_OPERATOR 5 +#define SCE_MSSQL_IDENTIFIER 6 +#define SCE_MSSQL_VARIABLE 7 +#define SCE_MSSQL_COLUMN_NAME 8 +#define SCE_MSSQL_STATEMENT 9 +#define SCE_MSSQL_DATATYPE 10 +#define SCE_MSSQL_SYSTABLE 11 +#define SCE_MSSQL_GLOBAL_VARIABLE 12 +#define SCE_MSSQL_FUNCTION 13 +#define SCE_MSSQL_STORED_PROCEDURE 14 +#define SCE_MSSQL_DEFAULT_PREF_DATATYPE 15 +#define SCE_MSSQL_COLUMN_NAME_2 16 +#define SCE_V_DEFAULT 0 +#define SCE_V_COMMENT 1 +#define SCE_V_COMMENTLINE 2 +#define SCE_V_COMMENTLINEBANG 3 +#define SCE_V_NUMBER 4 +#define SCE_V_WORD 5 +#define SCE_V_STRING 6 +#define SCE_V_WORD2 7 +#define SCE_V_WORD3 8 +#define SCE_V_PREPROCESSOR 9 +#define SCE_V_OPERATOR 10 +#define SCE_V_IDENTIFIER 11 +#define SCE_V_STRINGEOL 12 +#define SCE_V_USER 19 +#define SCE_V_COMMENT_WORD 20 +#define SCE_V_INPUT 21 +#define SCE_V_OUTPUT 22 +#define SCE_V_INOUT 23 +#define SCE_V_PORT_CONNECT 24 +#define SCE_KIX_DEFAULT 0 +#define SCE_KIX_COMMENT 1 +#define SCE_KIX_STRING1 2 +#define SCE_KIX_STRING2 3 +#define SCE_KIX_NUMBER 4 +#define SCE_KIX_VAR 5 +#define SCE_KIX_MACRO 6 +#define SCE_KIX_KEYWORD 7 +#define SCE_KIX_FUNCTIONS 8 +#define SCE_KIX_OPERATOR 9 +#define SCE_KIX_COMMENTSTREAM 10 +#define SCE_KIX_IDENTIFIER 31 +#define SCE_GC_DEFAULT 0 +#define SCE_GC_COMMENTLINE 1 +#define SCE_GC_COMMENTBLOCK 2 +#define SCE_GC_GLOBAL 3 +#define SCE_GC_EVENT 4 +#define SCE_GC_ATTRIBUTE 5 +#define SCE_GC_CONTROL 6 +#define SCE_GC_COMMAND 7 +#define SCE_GC_STRING 8 +#define SCE_GC_OPERATOR 9 +#define SCE_SN_DEFAULT 0 +#define SCE_SN_CODE 1 +#define SCE_SN_COMMENTLINE 2 +#define SCE_SN_COMMENTLINEBANG 3 +#define SCE_SN_NUMBER 4 +#define SCE_SN_WORD 5 +#define SCE_SN_STRING 6 +#define SCE_SN_WORD2 7 +#define SCE_SN_WORD3 8 +#define SCE_SN_PREPROCESSOR 9 +#define SCE_SN_OPERATOR 10 +#define SCE_SN_IDENTIFIER 11 +#define SCE_SN_STRINGEOL 12 +#define SCE_SN_REGEXTAG 13 +#define SCE_SN_SIGNAL 14 +#define SCE_SN_USER 19 +#define SCE_AU3_DEFAULT 0 +#define SCE_AU3_COMMENT 1 +#define SCE_AU3_COMMENTBLOCK 2 +#define SCE_AU3_NUMBER 3 +#define SCE_AU3_FUNCTION 4 +#define SCE_AU3_KEYWORD 5 +#define SCE_AU3_MACRO 6 +#define SCE_AU3_STRING 7 +#define SCE_AU3_OPERATOR 8 +#define SCE_AU3_VARIABLE 9 +#define SCE_AU3_SENT 10 +#define SCE_AU3_PREPROCESSOR 11 +#define SCE_AU3_SPECIAL 12 +#define SCE_AU3_EXPAND 13 +#define SCE_AU3_COMOBJ 14 +#define SCE_AU3_UDF 15 +#define SCE_APDL_DEFAULT 0 +#define SCE_APDL_COMMENT 1 +#define SCE_APDL_COMMENTBLOCK 2 +#define SCE_APDL_NUMBER 3 +#define SCE_APDL_STRING 4 +#define SCE_APDL_OPERATOR 5 +#define SCE_APDL_WORD 6 +#define SCE_APDL_PROCESSOR 7 +#define SCE_APDL_COMMAND 8 +#define SCE_APDL_SLASHCOMMAND 9 +#define SCE_APDL_STARCOMMAND 10 +#define SCE_APDL_ARGUMENT 11 +#define SCE_APDL_FUNCTION 12 +#define SCE_SH_DEFAULT 0 +#define SCE_SH_ERROR 1 +#define SCE_SH_COMMENTLINE 2 +#define SCE_SH_NUMBER 3 +#define SCE_SH_WORD 4 +#define SCE_SH_STRING 5 +#define SCE_SH_CHARACTER 6 +#define SCE_SH_OPERATOR 7 +#define SCE_SH_IDENTIFIER 8 +#define SCE_SH_SCALAR 9 +#define SCE_SH_PARAM 10 +#define SCE_SH_BACKTICKS 11 +#define SCE_SH_HERE_DELIM 12 +#define SCE_SH_HERE_Q 13 +#define SCE_ASN1_DEFAULT 0 +#define SCE_ASN1_COMMENT 1 +#define SCE_ASN1_IDENTIFIER 2 +#define SCE_ASN1_STRING 3 +#define SCE_ASN1_OID 4 +#define SCE_ASN1_SCALAR 5 +#define SCE_ASN1_KEYWORD 6 +#define SCE_ASN1_ATTRIBUTE 7 +#define SCE_ASN1_DESCRIPTOR 8 +#define SCE_ASN1_TYPE 9 +#define SCE_ASN1_OPERATOR 10 +#define SCE_VHDL_DEFAULT 0 +#define SCE_VHDL_COMMENT 1 +#define SCE_VHDL_COMMENTLINEBANG 2 +#define SCE_VHDL_NUMBER 3 +#define SCE_VHDL_STRING 4 +#define SCE_VHDL_OPERATOR 5 +#define SCE_VHDL_IDENTIFIER 6 +#define SCE_VHDL_STRINGEOL 7 +#define SCE_VHDL_KEYWORD 8 +#define SCE_VHDL_STDOPERATOR 9 +#define SCE_VHDL_ATTRIBUTE 10 +#define SCE_VHDL_STDFUNCTION 11 +#define SCE_VHDL_STDPACKAGE 12 +#define SCE_VHDL_STDTYPE 13 +#define SCE_VHDL_USERWORD 14 +#define SCE_VHDL_BLOCK_COMMENT 15 +#define SCE_CAML_DEFAULT 0 +#define SCE_CAML_IDENTIFIER 1 +#define SCE_CAML_TAGNAME 2 +#define SCE_CAML_KEYWORD 3 +#define SCE_CAML_KEYWORD2 4 +#define SCE_CAML_KEYWORD3 5 +#define SCE_CAML_LINENUM 6 +#define SCE_CAML_OPERATOR 7 +#define SCE_CAML_NUMBER 8 +#define SCE_CAML_CHAR 9 +#define SCE_CAML_WHITE 10 +#define SCE_CAML_STRING 11 +#define SCE_CAML_COMMENT 12 +#define SCE_CAML_COMMENT1 13 +#define SCE_CAML_COMMENT2 14 +#define SCE_CAML_COMMENT3 15 +#define SCE_HA_DEFAULT 0 +#define SCE_HA_IDENTIFIER 1 +#define SCE_HA_KEYWORD 2 +#define SCE_HA_NUMBER 3 +#define SCE_HA_STRING 4 +#define SCE_HA_CHARACTER 5 +#define SCE_HA_CLASS 6 +#define SCE_HA_MODULE 7 +#define SCE_HA_CAPITAL 8 +#define SCE_HA_DATA 9 +#define SCE_HA_IMPORT 10 +#define SCE_HA_OPERATOR 11 +#define SCE_HA_INSTANCE 12 +#define SCE_HA_COMMENTLINE 13 +#define SCE_HA_COMMENTBLOCK 14 +#define SCE_HA_COMMENTBLOCK2 15 +#define SCE_HA_COMMENTBLOCK3 16 +#define SCE_HA_PRAGMA 17 +#define SCE_HA_PREPROCESSOR 18 +#define SCE_HA_STRINGEOL 19 +#define SCE_HA_RESERVED_OPERATOR 20 +#define SCE_HA_LITERATE_COMMENT 21 +#define SCE_HA_LITERATE_CODEDELIM 22 +#define SCE_T3_DEFAULT 0 +#define SCE_T3_X_DEFAULT 1 +#define SCE_T3_PREPROCESSOR 2 +#define SCE_T3_BLOCK_COMMENT 3 +#define SCE_T3_LINE_COMMENT 4 +#define SCE_T3_OPERATOR 5 +#define SCE_T3_KEYWORD 6 +#define SCE_T3_NUMBER 7 +#define SCE_T3_IDENTIFIER 8 +#define SCE_T3_S_STRING 9 +#define SCE_T3_D_STRING 10 +#define SCE_T3_X_STRING 11 +#define SCE_T3_LIB_DIRECTIVE 12 +#define SCE_T3_MSG_PARAM 13 +#define SCE_T3_HTML_TAG 14 +#define SCE_T3_HTML_DEFAULT 15 +#define SCE_T3_HTML_STRING 16 +#define SCE_T3_USER1 17 +#define SCE_T3_USER2 18 +#define SCE_T3_USER3 19 +#define SCE_T3_BRACE 20 +#define SCE_REBOL_DEFAULT 0 +#define SCE_REBOL_COMMENTLINE 1 +#define SCE_REBOL_COMMENTBLOCK 2 +#define SCE_REBOL_PREFACE 3 +#define SCE_REBOL_OPERATOR 4 +#define SCE_REBOL_CHARACTER 5 +#define SCE_REBOL_QUOTEDSTRING 6 +#define SCE_REBOL_BRACEDSTRING 7 +#define SCE_REBOL_NUMBER 8 +#define SCE_REBOL_PAIR 9 +#define SCE_REBOL_TUPLE 10 +#define SCE_REBOL_BINARY 11 +#define SCE_REBOL_MONEY 12 +#define SCE_REBOL_ISSUE 13 +#define SCE_REBOL_TAG 14 +#define SCE_REBOL_FILE 15 +#define SCE_REBOL_EMAIL 16 +#define SCE_REBOL_URL 17 +#define SCE_REBOL_DATE 18 +#define SCE_REBOL_TIME 19 +#define SCE_REBOL_IDENTIFIER 20 +#define SCE_REBOL_WORD 21 +#define SCE_REBOL_WORD2 22 +#define SCE_REBOL_WORD3 23 +#define SCE_REBOL_WORD4 24 +#define SCE_REBOL_WORD5 25 +#define SCE_REBOL_WORD6 26 +#define SCE_REBOL_WORD7 27 +#define SCE_REBOL_WORD8 28 +#define SCE_SQL_DEFAULT 0 +#define SCE_SQL_COMMENT 1 +#define SCE_SQL_COMMENTLINE 2 +#define SCE_SQL_COMMENTDOC 3 +#define SCE_SQL_NUMBER 4 +#define SCE_SQL_WORD 5 +#define SCE_SQL_STRING 6 +#define SCE_SQL_CHARACTER 7 +#define SCE_SQL_SQLPLUS 8 +#define SCE_SQL_SQLPLUS_PROMPT 9 +#define SCE_SQL_OPERATOR 10 +#define SCE_SQL_IDENTIFIER 11 +#define SCE_SQL_SQLPLUS_COMMENT 13 +#define SCE_SQL_COMMENTLINEDOC 15 +#define SCE_SQL_WORD2 16 +#define SCE_SQL_COMMENTDOCKEYWORD 17 +#define SCE_SQL_COMMENTDOCKEYWORDERROR 18 +#define SCE_SQL_USER1 19 +#define SCE_SQL_USER2 20 +#define SCE_SQL_USER3 21 +#define SCE_SQL_USER4 22 +#define SCE_SQL_QUOTEDIDENTIFIER 23 +#define SCE_SQL_QOPERATOR 24 +#define SCE_ST_DEFAULT 0 +#define SCE_ST_STRING 1 +#define SCE_ST_NUMBER 2 +#define SCE_ST_COMMENT 3 +#define SCE_ST_SYMBOL 4 +#define SCE_ST_BINARY 5 +#define SCE_ST_BOOL 6 +#define SCE_ST_SELF 7 +#define SCE_ST_SUPER 8 +#define SCE_ST_NIL 9 +#define SCE_ST_GLOBAL 10 +#define SCE_ST_RETURN 11 +#define SCE_ST_SPECIAL 12 +#define SCE_ST_KWSEND 13 +#define SCE_ST_ASSIGN 14 +#define SCE_ST_CHARACTER 15 +#define SCE_ST_SPEC_SEL 16 +#define SCE_FS_DEFAULT 0 +#define SCE_FS_COMMENT 1 +#define SCE_FS_COMMENTLINE 2 +#define SCE_FS_COMMENTDOC 3 +#define SCE_FS_COMMENTLINEDOC 4 +#define SCE_FS_COMMENTDOCKEYWORD 5 +#define SCE_FS_COMMENTDOCKEYWORDERROR 6 +#define SCE_FS_KEYWORD 7 +#define SCE_FS_KEYWORD2 8 +#define SCE_FS_KEYWORD3 9 +#define SCE_FS_KEYWORD4 10 +#define SCE_FS_NUMBER 11 +#define SCE_FS_STRING 12 +#define SCE_FS_PREPROCESSOR 13 +#define SCE_FS_OPERATOR 14 +#define SCE_FS_IDENTIFIER 15 +#define SCE_FS_DATE 16 +#define SCE_FS_STRINGEOL 17 +#define SCE_FS_CONSTANT 18 +#define SCE_FS_WORDOPERATOR 19 +#define SCE_FS_DISABLEDCODE 20 +#define SCE_FS_DEFAULT_C 21 +#define SCE_FS_COMMENTDOC_C 22 +#define SCE_FS_COMMENTLINEDOC_C 23 +#define SCE_FS_KEYWORD_C 24 +#define SCE_FS_KEYWORD2_C 25 +#define SCE_FS_NUMBER_C 26 +#define SCE_FS_STRING_C 27 +#define SCE_FS_PREPROCESSOR_C 28 +#define SCE_FS_OPERATOR_C 29 +#define SCE_FS_IDENTIFIER_C 30 +#define SCE_FS_STRINGEOL_C 31 +#define SCE_CSOUND_DEFAULT 0 +#define SCE_CSOUND_COMMENT 1 +#define SCE_CSOUND_NUMBER 2 +#define SCE_CSOUND_OPERATOR 3 +#define SCE_CSOUND_INSTR 4 +#define SCE_CSOUND_IDENTIFIER 5 +#define SCE_CSOUND_OPCODE 6 +#define SCE_CSOUND_HEADERSTMT 7 +#define SCE_CSOUND_USERKEYWORD 8 +#define SCE_CSOUND_COMMENTBLOCK 9 +#define SCE_CSOUND_PARAM 10 +#define SCE_CSOUND_ARATE_VAR 11 +#define SCE_CSOUND_KRATE_VAR 12 +#define SCE_CSOUND_IRATE_VAR 13 +#define SCE_CSOUND_GLOBAL_VAR 14 +#define SCE_CSOUND_STRINGEOL 15 +#define SCE_INNO_DEFAULT 0 +#define SCE_INNO_COMMENT 1 +#define SCE_INNO_KEYWORD 2 +#define SCE_INNO_PARAMETER 3 +#define SCE_INNO_SECTION 4 +#define SCE_INNO_PREPROC 5 +#define SCE_INNO_INLINE_EXPANSION 6 +#define SCE_INNO_COMMENT_PASCAL 7 +#define SCE_INNO_KEYWORD_PASCAL 8 +#define SCE_INNO_KEYWORD_USER 9 +#define SCE_INNO_STRING_DOUBLE 10 +#define SCE_INNO_STRING_SINGLE 11 +#define SCE_INNO_IDENTIFIER 12 +#define SCE_OPAL_SPACE 0 +#define SCE_OPAL_COMMENT_BLOCK 1 +#define SCE_OPAL_COMMENT_LINE 2 +#define SCE_OPAL_INTEGER 3 +#define SCE_OPAL_KEYWORD 4 +#define SCE_OPAL_SORT 5 +#define SCE_OPAL_STRING 6 +#define SCE_OPAL_PAR 7 +#define SCE_OPAL_BOOL_CONST 8 +#define SCE_OPAL_DEFAULT 32 +#define SCE_SPICE_DEFAULT 0 +#define SCE_SPICE_IDENTIFIER 1 +#define SCE_SPICE_KEYWORD 2 +#define SCE_SPICE_KEYWORD2 3 +#define SCE_SPICE_KEYWORD3 4 +#define SCE_SPICE_NUMBER 5 +#define SCE_SPICE_DELIMITER 6 +#define SCE_SPICE_VALUE 7 +#define SCE_SPICE_COMMENTLINE 8 +#define SCE_CMAKE_DEFAULT 0 +#define SCE_CMAKE_COMMENT 1 +#define SCE_CMAKE_STRINGDQ 2 +#define SCE_CMAKE_STRINGLQ 3 +#define SCE_CMAKE_STRINGRQ 4 +#define SCE_CMAKE_COMMANDS 5 +#define SCE_CMAKE_PARAMETERS 6 +#define SCE_CMAKE_VARIABLE 7 +#define SCE_CMAKE_USERDEFINED 8 +#define SCE_CMAKE_WHILEDEF 9 +#define SCE_CMAKE_FOREACHDEF 10 +#define SCE_CMAKE_IFDEFINEDEF 11 +#define SCE_CMAKE_MACRODEF 12 +#define SCE_CMAKE_STRINGVAR 13 +#define SCE_CMAKE_NUMBER 14 +#define SCE_GAP_DEFAULT 0 +#define SCE_GAP_IDENTIFIER 1 +#define SCE_GAP_KEYWORD 2 +#define SCE_GAP_KEYWORD2 3 +#define SCE_GAP_KEYWORD3 4 +#define SCE_GAP_KEYWORD4 5 +#define SCE_GAP_STRING 6 +#define SCE_GAP_CHAR 7 +#define SCE_GAP_OPERATOR 8 +#define SCE_GAP_COMMENT 9 +#define SCE_GAP_NUMBER 10 +#define SCE_GAP_STRINGEOL 11 +#define SCE_PLM_DEFAULT 0 +#define SCE_PLM_COMMENT 1 +#define SCE_PLM_STRING 2 +#define SCE_PLM_NUMBER 3 +#define SCE_PLM_IDENTIFIER 4 +#define SCE_PLM_OPERATOR 5 +#define SCE_PLM_CONTROL 6 +#define SCE_PLM_KEYWORD 7 +#define SCE_ABL_DEFAULT 0 +#define SCE_ABL_NUMBER 1 +#define SCE_ABL_WORD 2 +#define SCE_ABL_STRING 3 +#define SCE_ABL_CHARACTER 4 +#define SCE_ABL_PREPROCESSOR 5 +#define SCE_ABL_OPERATOR 6 +#define SCE_ABL_IDENTIFIER 7 +#define SCE_ABL_BLOCK 8 +#define SCE_ABL_END 9 +#define SCE_ABL_COMMENT 10 +#define SCE_ABL_TASKMARKER 11 +#define SCE_ABL_LINECOMMENT 12 +#define SCE_ABAQUS_DEFAULT 0 +#define SCE_ABAQUS_COMMENT 1 +#define SCE_ABAQUS_COMMENTBLOCK 2 +#define SCE_ABAQUS_NUMBER 3 +#define SCE_ABAQUS_STRING 4 +#define SCE_ABAQUS_OPERATOR 5 +#define SCE_ABAQUS_WORD 6 +#define SCE_ABAQUS_PROCESSOR 7 +#define SCE_ABAQUS_COMMAND 8 +#define SCE_ABAQUS_SLASHCOMMAND 9 +#define SCE_ABAQUS_STARCOMMAND 10 +#define SCE_ABAQUS_ARGUMENT 11 +#define SCE_ABAQUS_FUNCTION 12 +#define SCE_ASY_DEFAULT 0 +#define SCE_ASY_COMMENT 1 +#define SCE_ASY_COMMENTLINE 2 +#define SCE_ASY_NUMBER 3 +#define SCE_ASY_WORD 4 +#define SCE_ASY_STRING 5 +#define SCE_ASY_CHARACTER 6 +#define SCE_ASY_OPERATOR 7 +#define SCE_ASY_IDENTIFIER 8 +#define SCE_ASY_STRINGEOL 9 +#define SCE_ASY_COMMENTLINEDOC 10 +#define SCE_ASY_WORD2 11 +#define SCE_R_DEFAULT 0 +#define SCE_R_COMMENT 1 +#define SCE_R_KWORD 2 +#define SCE_R_BASEKWORD 3 +#define SCE_R_OTHERKWORD 4 +#define SCE_R_NUMBER 5 +#define SCE_R_STRING 6 +#define SCE_R_STRING2 7 +#define SCE_R_OPERATOR 8 +#define SCE_R_IDENTIFIER 9 +#define SCE_R_INFIX 10 +#define SCE_R_INFIXEOL 11 +#define SCE_R_BACKTICKS 12 +#define SCE_R_RAWSTRING 13 +#define SCE_R_RAWSTRING2 14 +#define SCE_R_ESCAPESEQUENCE 15 +#define SCE_MAGIK_DEFAULT 0 +#define SCE_MAGIK_COMMENT 1 +#define SCE_MAGIK_HYPER_COMMENT 16 +#define SCE_MAGIK_STRING 2 +#define SCE_MAGIK_CHARACTER 3 +#define SCE_MAGIK_NUMBER 4 +#define SCE_MAGIK_IDENTIFIER 5 +#define SCE_MAGIK_OPERATOR 6 +#define SCE_MAGIK_FLOW 7 +#define SCE_MAGIK_CONTAINER 8 +#define SCE_MAGIK_BRACKET_BLOCK 9 +#define SCE_MAGIK_BRACE_BLOCK 10 +#define SCE_MAGIK_SQBRACKET_BLOCK 11 +#define SCE_MAGIK_UNKNOWN_KEYWORD 12 +#define SCE_MAGIK_KEYWORD 13 +#define SCE_MAGIK_PRAGMA 14 +#define SCE_MAGIK_SYMBOL 15 +#define SCE_POWERSHELL_DEFAULT 0 +#define SCE_POWERSHELL_COMMENT 1 +#define SCE_POWERSHELL_STRING 2 +#define SCE_POWERSHELL_CHARACTER 3 +#define SCE_POWERSHELL_NUMBER 4 +#define SCE_POWERSHELL_VARIABLE 5 +#define SCE_POWERSHELL_OPERATOR 6 +#define SCE_POWERSHELL_IDENTIFIER 7 +#define SCE_POWERSHELL_KEYWORD 8 +#define SCE_POWERSHELL_CMDLET 9 +#define SCE_POWERSHELL_ALIAS 10 +#define SCE_POWERSHELL_FUNCTION 11 +#define SCE_POWERSHELL_USER1 12 +#define SCE_POWERSHELL_COMMENTSTREAM 13 +#define SCE_POWERSHELL_HERE_STRING 14 +#define SCE_POWERSHELL_HERE_CHARACTER 15 +#define SCE_POWERSHELL_COMMENTDOCKEYWORD 16 +#define SCE_MYSQL_DEFAULT 0 +#define SCE_MYSQL_COMMENT 1 +#define SCE_MYSQL_COMMENTLINE 2 +#define SCE_MYSQL_VARIABLE 3 +#define SCE_MYSQL_SYSTEMVARIABLE 4 +#define SCE_MYSQL_KNOWNSYSTEMVARIABLE 5 +#define SCE_MYSQL_NUMBER 6 +#define SCE_MYSQL_MAJORKEYWORD 7 +#define SCE_MYSQL_KEYWORD 8 +#define SCE_MYSQL_DATABASEOBJECT 9 +#define SCE_MYSQL_PROCEDUREKEYWORD 10 +#define SCE_MYSQL_STRING 11 +#define SCE_MYSQL_SQSTRING 12 +#define SCE_MYSQL_DQSTRING 13 +#define SCE_MYSQL_OPERATOR 14 +#define SCE_MYSQL_FUNCTION 15 +#define SCE_MYSQL_IDENTIFIER 16 +#define SCE_MYSQL_QUOTEDIDENTIFIER 17 +#define SCE_MYSQL_USER1 18 +#define SCE_MYSQL_USER2 19 +#define SCE_MYSQL_USER3 20 +#define SCE_MYSQL_HIDDENCOMMAND 21 +#define SCE_MYSQL_PLACEHOLDER 22 +#define SCE_PO_DEFAULT 0 +#define SCE_PO_COMMENT 1 +#define SCE_PO_MSGID 2 +#define SCE_PO_MSGID_TEXT 3 +#define SCE_PO_MSGSTR 4 +#define SCE_PO_MSGSTR_TEXT 5 +#define SCE_PO_MSGCTXT 6 +#define SCE_PO_MSGCTXT_TEXT 7 +#define SCE_PO_FUZZY 8 +#define SCE_PO_PROGRAMMER_COMMENT 9 +#define SCE_PO_REFERENCE 10 +#define SCE_PO_FLAGS 11 +#define SCE_PO_MSGID_TEXT_EOL 12 +#define SCE_PO_MSGSTR_TEXT_EOL 13 +#define SCE_PO_MSGCTXT_TEXT_EOL 14 +#define SCE_PO_ERROR 15 +#define SCE_PAS_DEFAULT 0 +#define SCE_PAS_IDENTIFIER 1 +#define SCE_PAS_COMMENT 2 +#define SCE_PAS_COMMENT2 3 +#define SCE_PAS_COMMENTLINE 4 +#define SCE_PAS_PREPROCESSOR 5 +#define SCE_PAS_PREPROCESSOR2 6 +#define SCE_PAS_NUMBER 7 +#define SCE_PAS_HEXNUMBER 8 +#define SCE_PAS_WORD 9 +#define SCE_PAS_STRING 10 +#define SCE_PAS_STRINGEOL 11 +#define SCE_PAS_CHARACTER 12 +#define SCE_PAS_OPERATOR 13 +#define SCE_PAS_ASM 14 +#define SCE_SORCUS_DEFAULT 0 +#define SCE_SORCUS_COMMAND 1 +#define SCE_SORCUS_PARAMETER 2 +#define SCE_SORCUS_COMMENTLINE 3 +#define SCE_SORCUS_STRING 4 +#define SCE_SORCUS_STRINGEOL 5 +#define SCE_SORCUS_IDENTIFIER 6 +#define SCE_SORCUS_OPERATOR 7 +#define SCE_SORCUS_NUMBER 8 +#define SCE_SORCUS_CONSTANT 9 +#define SCE_POWERPRO_DEFAULT 0 +#define SCE_POWERPRO_COMMENTBLOCK 1 +#define SCE_POWERPRO_COMMENTLINE 2 +#define SCE_POWERPRO_NUMBER 3 +#define SCE_POWERPRO_WORD 4 +#define SCE_POWERPRO_WORD2 5 +#define SCE_POWERPRO_WORD3 6 +#define SCE_POWERPRO_WORD4 7 +#define SCE_POWERPRO_DOUBLEQUOTEDSTRING 8 +#define SCE_POWERPRO_SINGLEQUOTEDSTRING 9 +#define SCE_POWERPRO_LINECONTINUE 10 +#define SCE_POWERPRO_OPERATOR 11 +#define SCE_POWERPRO_IDENTIFIER 12 +#define SCE_POWERPRO_STRINGEOL 13 +#define SCE_POWERPRO_VERBATIM 14 +#define SCE_POWERPRO_ALTQUOTE 15 +#define SCE_POWERPRO_FUNCTION 16 +#define SCE_SML_DEFAULT 0 +#define SCE_SML_IDENTIFIER 1 +#define SCE_SML_TAGNAME 2 +#define SCE_SML_KEYWORD 3 +#define SCE_SML_KEYWORD2 4 +#define SCE_SML_KEYWORD3 5 +#define SCE_SML_LINENUM 6 +#define SCE_SML_OPERATOR 7 +#define SCE_SML_NUMBER 8 +#define SCE_SML_CHAR 9 +#define SCE_SML_STRING 11 +#define SCE_SML_COMMENT 12 +#define SCE_SML_COMMENT1 13 +#define SCE_SML_COMMENT2 14 +#define SCE_SML_COMMENT3 15 +#define SCE_MARKDOWN_DEFAULT 0 +#define SCE_MARKDOWN_LINE_BEGIN 1 +#define SCE_MARKDOWN_STRONG1 2 +#define SCE_MARKDOWN_STRONG2 3 +#define SCE_MARKDOWN_EM1 4 +#define SCE_MARKDOWN_EM2 5 +#define SCE_MARKDOWN_HEADER1 6 +#define SCE_MARKDOWN_HEADER2 7 +#define SCE_MARKDOWN_HEADER3 8 +#define SCE_MARKDOWN_HEADER4 9 +#define SCE_MARKDOWN_HEADER5 10 +#define SCE_MARKDOWN_HEADER6 11 +#define SCE_MARKDOWN_PRECHAR 12 +#define SCE_MARKDOWN_ULIST_ITEM 13 +#define SCE_MARKDOWN_OLIST_ITEM 14 +#define SCE_MARKDOWN_BLOCKQUOTE 15 +#define SCE_MARKDOWN_STRIKEOUT 16 +#define SCE_MARKDOWN_HRULE 17 +#define SCE_MARKDOWN_LINK 18 +#define SCE_MARKDOWN_CODE 19 +#define SCE_MARKDOWN_CODE2 20 +#define SCE_MARKDOWN_CODEBK 21 +#define SCE_TXT2TAGS_DEFAULT 0 +#define SCE_TXT2TAGS_LINE_BEGIN 1 +#define SCE_TXT2TAGS_STRONG1 2 +#define SCE_TXT2TAGS_STRONG2 3 +#define SCE_TXT2TAGS_EM1 4 +#define SCE_TXT2TAGS_EM2 5 +#define SCE_TXT2TAGS_HEADER1 6 +#define SCE_TXT2TAGS_HEADER2 7 +#define SCE_TXT2TAGS_HEADER3 8 +#define SCE_TXT2TAGS_HEADER4 9 +#define SCE_TXT2TAGS_HEADER5 10 +#define SCE_TXT2TAGS_HEADER6 11 +#define SCE_TXT2TAGS_PRECHAR 12 +#define SCE_TXT2TAGS_ULIST_ITEM 13 +#define SCE_TXT2TAGS_OLIST_ITEM 14 +#define SCE_TXT2TAGS_BLOCKQUOTE 15 +#define SCE_TXT2TAGS_STRIKEOUT 16 +#define SCE_TXT2TAGS_HRULE 17 +#define SCE_TXT2TAGS_LINK 18 +#define SCE_TXT2TAGS_CODE 19 +#define SCE_TXT2TAGS_CODE2 20 +#define SCE_TXT2TAGS_CODEBK 21 +#define SCE_TXT2TAGS_COMMENT 22 +#define SCE_TXT2TAGS_OPTION 23 +#define SCE_TXT2TAGS_PREPROC 24 +#define SCE_TXT2TAGS_POSTPROC 25 +#define SCE_A68K_DEFAULT 0 +#define SCE_A68K_COMMENT 1 +#define SCE_A68K_NUMBER_DEC 2 +#define SCE_A68K_NUMBER_BIN 3 +#define SCE_A68K_NUMBER_HEX 4 +#define SCE_A68K_STRING1 5 +#define SCE_A68K_OPERATOR 6 +#define SCE_A68K_CPUINSTRUCTION 7 +#define SCE_A68K_EXTINSTRUCTION 8 +#define SCE_A68K_REGISTER 9 +#define SCE_A68K_DIRECTIVE 10 +#define SCE_A68K_MACRO_ARG 11 +#define SCE_A68K_LABEL 12 +#define SCE_A68K_STRING2 13 +#define SCE_A68K_IDENTIFIER 14 +#define SCE_A68K_MACRO_DECLARATION 15 +#define SCE_A68K_COMMENT_WORD 16 +#define SCE_A68K_COMMENT_SPECIAL 17 +#define SCE_A68K_COMMENT_DOXYGEN 18 +#define SCE_MODULA_DEFAULT 0 +#define SCE_MODULA_COMMENT 1 +#define SCE_MODULA_DOXYCOMM 2 +#define SCE_MODULA_DOXYKEY 3 +#define SCE_MODULA_KEYWORD 4 +#define SCE_MODULA_RESERVED 5 +#define SCE_MODULA_NUMBER 6 +#define SCE_MODULA_BASENUM 7 +#define SCE_MODULA_FLOAT 8 +#define SCE_MODULA_STRING 9 +#define SCE_MODULA_STRSPEC 10 +#define SCE_MODULA_CHAR 11 +#define SCE_MODULA_CHARSPEC 12 +#define SCE_MODULA_PROC 13 +#define SCE_MODULA_PRAGMA 14 +#define SCE_MODULA_PRGKEY 15 +#define SCE_MODULA_OPERATOR 16 +#define SCE_MODULA_BADSTR 17 +#define SCE_COFFEESCRIPT_DEFAULT 0 +#define SCE_COFFEESCRIPT_COMMENT 1 +#define SCE_COFFEESCRIPT_COMMENTLINE 2 +#define SCE_COFFEESCRIPT_COMMENTDOC 3 +#define SCE_COFFEESCRIPT_NUMBER 4 +#define SCE_COFFEESCRIPT_WORD 5 +#define SCE_COFFEESCRIPT_STRING 6 +#define SCE_COFFEESCRIPT_CHARACTER 7 +#define SCE_COFFEESCRIPT_UUID 8 +#define SCE_COFFEESCRIPT_PREPROCESSOR 9 +#define SCE_COFFEESCRIPT_OPERATOR 10 +#define SCE_COFFEESCRIPT_IDENTIFIER 11 +#define SCE_COFFEESCRIPT_STRINGEOL 12 +#define SCE_COFFEESCRIPT_VERBATIM 13 +#define SCE_COFFEESCRIPT_REGEX 14 +#define SCE_COFFEESCRIPT_COMMENTLINEDOC 15 +#define SCE_COFFEESCRIPT_WORD2 16 +#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORD 17 +#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR 18 +#define SCE_COFFEESCRIPT_GLOBALCLASS 19 +#define SCE_COFFEESCRIPT_STRINGRAW 20 +#define SCE_COFFEESCRIPT_TRIPLEVERBATIM 21 +#define SCE_COFFEESCRIPT_COMMENTBLOCK 22 +#define SCE_COFFEESCRIPT_VERBOSE_REGEX 23 +#define SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT 24 +#define SCE_COFFEESCRIPT_INSTANCEPROPERTY 25 +#define SCE_AVS_DEFAULT 0 +#define SCE_AVS_COMMENTBLOCK 1 +#define SCE_AVS_COMMENTBLOCKN 2 +#define SCE_AVS_COMMENTLINE 3 +#define SCE_AVS_NUMBER 4 +#define SCE_AVS_OPERATOR 5 +#define SCE_AVS_IDENTIFIER 6 +#define SCE_AVS_STRING 7 +#define SCE_AVS_TRIPLESTRING 8 +#define SCE_AVS_KEYWORD 9 +#define SCE_AVS_FILTER 10 +#define SCE_AVS_PLUGIN 11 +#define SCE_AVS_FUNCTION 12 +#define SCE_AVS_CLIPPROP 13 +#define SCE_AVS_USERDFN 14 +#define SCE_ECL_DEFAULT 0 +#define SCE_ECL_COMMENT 1 +#define SCE_ECL_COMMENTLINE 2 +#define SCE_ECL_NUMBER 3 +#define SCE_ECL_STRING 4 +#define SCE_ECL_WORD0 5 +#define SCE_ECL_OPERATOR 6 +#define SCE_ECL_CHARACTER 7 +#define SCE_ECL_UUID 8 +#define SCE_ECL_PREPROCESSOR 9 +#define SCE_ECL_UNKNOWN 10 +#define SCE_ECL_IDENTIFIER 11 +#define SCE_ECL_STRINGEOL 12 +#define SCE_ECL_VERBATIM 13 +#define SCE_ECL_REGEX 14 +#define SCE_ECL_COMMENTLINEDOC 15 +#define SCE_ECL_WORD1 16 +#define SCE_ECL_COMMENTDOCKEYWORD 17 +#define SCE_ECL_COMMENTDOCKEYWORDERROR 18 +#define SCE_ECL_WORD2 19 +#define SCE_ECL_WORD3 20 +#define SCE_ECL_WORD4 21 +#define SCE_ECL_WORD5 22 +#define SCE_ECL_COMMENTDOC 23 +#define SCE_ECL_ADDED 24 +#define SCE_ECL_DELETED 25 +#define SCE_ECL_CHANGED 26 +#define SCE_ECL_MOVED 27 +#define SCE_OSCRIPT_DEFAULT 0 +#define SCE_OSCRIPT_LINE_COMMENT 1 +#define SCE_OSCRIPT_BLOCK_COMMENT 2 +#define SCE_OSCRIPT_DOC_COMMENT 3 +#define SCE_OSCRIPT_PREPROCESSOR 4 +#define SCE_OSCRIPT_NUMBER 5 +#define SCE_OSCRIPT_SINGLEQUOTE_STRING 6 +#define SCE_OSCRIPT_DOUBLEQUOTE_STRING 7 +#define SCE_OSCRIPT_CONSTANT 8 +#define SCE_OSCRIPT_IDENTIFIER 9 +#define SCE_OSCRIPT_GLOBAL 10 +#define SCE_OSCRIPT_KEYWORD 11 +#define SCE_OSCRIPT_OPERATOR 12 +#define SCE_OSCRIPT_LABEL 13 +#define SCE_OSCRIPT_TYPE 14 +#define SCE_OSCRIPT_FUNCTION 15 +#define SCE_OSCRIPT_OBJECT 16 +#define SCE_OSCRIPT_PROPERTY 17 +#define SCE_OSCRIPT_METHOD 18 +#define SCE_VISUALPROLOG_DEFAULT 0 +#define SCE_VISUALPROLOG_KEY_MAJOR 1 +#define SCE_VISUALPROLOG_KEY_MINOR 2 +#define SCE_VISUALPROLOG_KEY_DIRECTIVE 3 +#define SCE_VISUALPROLOG_COMMENT_BLOCK 4 +#define SCE_VISUALPROLOG_COMMENT_LINE 5 +#define SCE_VISUALPROLOG_COMMENT_KEY 6 +#define SCE_VISUALPROLOG_COMMENT_KEY_ERROR 7 +#define SCE_VISUALPROLOG_IDENTIFIER 8 +#define SCE_VISUALPROLOG_VARIABLE 9 +#define SCE_VISUALPROLOG_ANONYMOUS 10 +#define SCE_VISUALPROLOG_NUMBER 11 +#define SCE_VISUALPROLOG_OPERATOR 12 +#define SCE_VISUALPROLOG_UNUSED1 13 +#define SCE_VISUALPROLOG_UNUSED2 14 +#define SCE_VISUALPROLOG_UNUSED3 15 +#define SCE_VISUALPROLOG_STRING_QUOTE 16 +#define SCE_VISUALPROLOG_STRING_ESCAPE 17 +#define SCE_VISUALPROLOG_STRING_ESCAPE_ERROR 18 +#define SCE_VISUALPROLOG_UNUSED4 19 +#define SCE_VISUALPROLOG_STRING 20 +#define SCE_VISUALPROLOG_UNUSED5 21 +#define SCE_VISUALPROLOG_STRING_EOL 22 +#define SCE_VISUALPROLOG_EMBEDDED 23 +#define SCE_VISUALPROLOG_PLACEHOLDER 24 +#define SCE_STTXT_DEFAULT 0 +#define SCE_STTXT_COMMENT 1 +#define SCE_STTXT_COMMENTLINE 2 +#define SCE_STTXT_KEYWORD 3 +#define SCE_STTXT_TYPE 4 +#define SCE_STTXT_FUNCTION 5 +#define SCE_STTXT_FB 6 +#define SCE_STTXT_NUMBER 7 +#define SCE_STTXT_HEXNUMBER 8 +#define SCE_STTXT_PRAGMA 9 +#define SCE_STTXT_OPERATOR 10 +#define SCE_STTXT_CHARACTER 11 +#define SCE_STTXT_STRING1 12 +#define SCE_STTXT_STRING2 13 +#define SCE_STTXT_STRINGEOL 14 +#define SCE_STTXT_IDENTIFIER 15 +#define SCE_STTXT_DATETIME 16 +#define SCE_STTXT_VARS 17 +#define SCE_STTXT_PRAGMAS 18 +#define SCE_KVIRC_DEFAULT 0 +#define SCE_KVIRC_COMMENT 1 +#define SCE_KVIRC_COMMENTBLOCK 2 +#define SCE_KVIRC_STRING 3 +#define SCE_KVIRC_WORD 4 +#define SCE_KVIRC_KEYWORD 5 +#define SCE_KVIRC_FUNCTION_KEYWORD 6 +#define SCE_KVIRC_FUNCTION 7 +#define SCE_KVIRC_VARIABLE 8 +#define SCE_KVIRC_NUMBER 9 +#define SCE_KVIRC_OPERATOR 10 +#define SCE_KVIRC_STRING_FUNCTION 11 +#define SCE_KVIRC_STRING_VARIABLE 12 +#define SCE_RUST_DEFAULT 0 +#define SCE_RUST_COMMENTBLOCK 1 +#define SCE_RUST_COMMENTLINE 2 +#define SCE_RUST_COMMENTBLOCKDOC 3 +#define SCE_RUST_COMMENTLINEDOC 4 +#define SCE_RUST_NUMBER 5 +#define SCE_RUST_WORD 6 +#define SCE_RUST_WORD2 7 +#define SCE_RUST_WORD3 8 +#define SCE_RUST_WORD4 9 +#define SCE_RUST_WORD5 10 +#define SCE_RUST_WORD6 11 +#define SCE_RUST_WORD7 12 +#define SCE_RUST_STRING 13 +#define SCE_RUST_STRINGR 14 +#define SCE_RUST_CHARACTER 15 +#define SCE_RUST_OPERATOR 16 +#define SCE_RUST_IDENTIFIER 17 +#define SCE_RUST_LIFETIME 18 +#define SCE_RUST_MACRO 19 +#define SCE_RUST_LEXERROR 20 +#define SCE_RUST_BYTESTRING 21 +#define SCE_RUST_BYTESTRINGR 22 +#define SCE_RUST_BYTECHARACTER 23 +#define SCE_DMAP_DEFAULT 0 +#define SCE_DMAP_COMMENT 1 +#define SCE_DMAP_NUMBER 2 +#define SCE_DMAP_STRING1 3 +#define SCE_DMAP_STRING2 4 +#define SCE_DMAP_STRINGEOL 5 +#define SCE_DMAP_OPERATOR 6 +#define SCE_DMAP_IDENTIFIER 7 +#define SCE_DMAP_WORD 8 +#define SCE_DMAP_WORD2 9 +#define SCE_DMAP_WORD3 10 +#define SCE_DMIS_DEFAULT 0 +#define SCE_DMIS_COMMENT 1 +#define SCE_DMIS_STRING 2 +#define SCE_DMIS_NUMBER 3 +#define SCE_DMIS_KEYWORD 4 +#define SCE_DMIS_MAJORWORD 5 +#define SCE_DMIS_MINORWORD 6 +#define SCE_DMIS_UNSUPPORTED_MAJOR 7 +#define SCE_DMIS_UNSUPPORTED_MINOR 8 +#define SCE_DMIS_LABEL 9 +#define SCE_REG_DEFAULT 0 +#define SCE_REG_COMMENT 1 +#define SCE_REG_VALUENAME 2 +#define SCE_REG_STRING 3 +#define SCE_REG_HEXDIGIT 4 +#define SCE_REG_VALUETYPE 5 +#define SCE_REG_ADDEDKEY 6 +#define SCE_REG_DELETEDKEY 7 +#define SCE_REG_ESCAPED 8 +#define SCE_REG_KEYPATH_GUID 9 +#define SCE_REG_STRING_GUID 10 +#define SCE_REG_PARAMETER 11 +#define SCE_REG_OPERATOR 12 +#define SCE_BIBTEX_DEFAULT 0 +#define SCE_BIBTEX_ENTRY 1 +#define SCE_BIBTEX_UNKNOWN_ENTRY 2 +#define SCE_BIBTEX_KEY 3 +#define SCE_BIBTEX_PARAMETER 4 +#define SCE_BIBTEX_VALUE 5 +#define SCE_BIBTEX_COMMENT 6 +#define SCE_HEX_DEFAULT 0 +#define SCE_HEX_RECSTART 1 +#define SCE_HEX_RECTYPE 2 +#define SCE_HEX_RECTYPE_UNKNOWN 3 +#define SCE_HEX_BYTECOUNT 4 +#define SCE_HEX_BYTECOUNT_WRONG 5 +#define SCE_HEX_NOADDRESS 6 +#define SCE_HEX_DATAADDRESS 7 +#define SCE_HEX_RECCOUNT 8 +#define SCE_HEX_STARTADDRESS 9 +#define SCE_HEX_ADDRESSFIELD_UNKNOWN 10 +#define SCE_HEX_EXTENDEDADDRESS 11 +#define SCE_HEX_DATA_ODD 12 +#define SCE_HEX_DATA_EVEN 13 +#define SCE_HEX_DATA_UNKNOWN 14 +#define SCE_HEX_DATA_EMPTY 15 +#define SCE_HEX_CHECKSUM 16 +#define SCE_HEX_CHECKSUM_WRONG 17 +#define SCE_HEX_GARBAGE 18 +#define SCE_JSON_DEFAULT 0 +#define SCE_JSON_NUMBER 1 +#define SCE_JSON_STRING 2 +#define SCE_JSON_STRINGEOL 3 +#define SCE_JSON_PROPERTYNAME 4 +#define SCE_JSON_ESCAPESEQUENCE 5 +#define SCE_JSON_LINECOMMENT 6 +#define SCE_JSON_BLOCKCOMMENT 7 +#define SCE_JSON_OPERATOR 8 +#define SCE_JSON_URI 9 +#define SCE_JSON_COMPACTIRI 10 +#define SCE_JSON_KEYWORD 11 +#define SCE_JSON_LDKEYWORD 12 +#define SCE_JSON_ERROR 13 +#define SCE_EDI_DEFAULT 0 +#define SCE_EDI_SEGMENTSTART 1 +#define SCE_EDI_SEGMENTEND 2 +#define SCE_EDI_SEP_ELEMENT 3 +#define SCE_EDI_SEP_COMPOSITE 4 +#define SCE_EDI_SEP_RELEASE 5 +#define SCE_EDI_UNA 6 +#define SCE_EDI_UNH 7 +#define SCE_EDI_BADSEGMENT 8 +#define SCE_STATA_DEFAULT 0 +#define SCE_STATA_COMMENT 1 +#define SCE_STATA_COMMENTLINE 2 +#define SCE_STATA_COMMENTBLOCK 3 +#define SCE_STATA_NUMBER 4 +#define SCE_STATA_OPERATOR 5 +#define SCE_STATA_IDENTIFIER 6 +#define SCE_STATA_STRING 7 +#define SCE_STATA_TYPE 8 +#define SCE_STATA_WORD 9 +#define SCE_STATA_GLOBAL_MACRO 10 +#define SCE_STATA_MACRO 11 +#define SCE_SAS_DEFAULT 0 +#define SCE_SAS_COMMENT 1 +#define SCE_SAS_COMMENTLINE 2 +#define SCE_SAS_COMMENTBLOCK 3 +#define SCE_SAS_NUMBER 4 +#define SCE_SAS_OPERATOR 5 +#define SCE_SAS_IDENTIFIER 6 +#define SCE_SAS_STRING 7 +#define SCE_SAS_TYPE 8 +#define SCE_SAS_WORD 9 +#define SCE_SAS_GLOBAL_MACRO 10 +#define SCE_SAS_MACRO 11 +#define SCE_SAS_MACRO_KEYWORD 12 +#define SCE_SAS_BLOCK_KEYWORD 13 +#define SCE_SAS_MACRO_FUNCTION 14 +#define SCE_SAS_STATEMENT 15 +#define SCE_NIM_DEFAULT 0 +#define SCE_NIM_COMMENT 1 +#define SCE_NIM_COMMENTDOC 2 +#define SCE_NIM_COMMENTLINE 3 +#define SCE_NIM_COMMENTLINEDOC 4 +#define SCE_NIM_NUMBER 5 +#define SCE_NIM_STRING 6 +#define SCE_NIM_CHARACTER 7 +#define SCE_NIM_WORD 8 +#define SCE_NIM_TRIPLE 9 +#define SCE_NIM_TRIPLEDOUBLE 10 +#define SCE_NIM_BACKTICKS 11 +#define SCE_NIM_FUNCNAME 12 +#define SCE_NIM_STRINGEOL 13 +#define SCE_NIM_NUMERROR 14 +#define SCE_NIM_OPERATOR 15 +#define SCE_NIM_IDENTIFIER 16 +#define SCE_CIL_DEFAULT 0 +#define SCE_CIL_COMMENT 1 +#define SCE_CIL_COMMENTLINE 2 +#define SCE_CIL_WORD 3 +#define SCE_CIL_WORD2 4 +#define SCE_CIL_WORD3 5 +#define SCE_CIL_STRING 6 +#define SCE_CIL_LABEL 7 +#define SCE_CIL_OPERATOR 8 +#define SCE_CIL_IDENTIFIER 9 +#define SCE_CIL_STRINGEOL 10 +#define SCE_X12_DEFAULT 0 +#define SCE_X12_BAD 1 +#define SCE_X12_ENVELOPE 2 +#define SCE_X12_FUNCTIONGROUP 3 +#define SCE_X12_TRANSACTIONSET 4 +#define SCE_X12_SEGMENTHEADER 5 +#define SCE_X12_SEGMENTEND 6 +#define SCE_X12_SEP_ELEMENT 7 +#define SCE_X12_SEP_SUBELEMENT 8 +#define SCE_DF_DEFAULT 0 +#define SCE_DF_IDENTIFIER 1 +#define SCE_DF_METATAG 2 +#define SCE_DF_IMAGE 3 +#define SCE_DF_COMMENTLINE 4 +#define SCE_DF_PREPROCESSOR 5 +#define SCE_DF_PREPROCESSOR2 6 +#define SCE_DF_NUMBER 7 +#define SCE_DF_HEXNUMBER 8 +#define SCE_DF_WORD 9 +#define SCE_DF_STRING 10 +#define SCE_DF_STRINGEOL 11 +#define SCE_DF_SCOPEWORD 12 +#define SCE_DF_OPERATOR 13 +#define SCE_DF_ICODE 14 +#define SCE_HOLLYWOOD_DEFAULT 0 +#define SCE_HOLLYWOOD_COMMENT 1 +#define SCE_HOLLYWOOD_COMMENTBLOCK 2 +#define SCE_HOLLYWOOD_NUMBER 3 +#define SCE_HOLLYWOOD_KEYWORD 4 +#define SCE_HOLLYWOOD_STDAPI 5 +#define SCE_HOLLYWOOD_PLUGINAPI 6 +#define SCE_HOLLYWOOD_PLUGINMETHOD 7 +#define SCE_HOLLYWOOD_STRING 8 +#define SCE_HOLLYWOOD_STRINGBLOCK 9 +#define SCE_HOLLYWOOD_PREPROCESSOR 10 +#define SCE_HOLLYWOOD_OPERATOR 11 +#define SCE_HOLLYWOOD_IDENTIFIER 12 +#define SCE_HOLLYWOOD_CONSTANT 13 +#define SCE_HOLLYWOOD_HEXNUMBER 14 +#define SCE_RAKU_DEFAULT 0 +#define SCE_RAKU_ERROR 1 +#define SCE_RAKU_COMMENTLINE 2 +#define SCE_RAKU_COMMENTEMBED 3 +#define SCE_RAKU_POD 4 +#define SCE_RAKU_CHARACTER 5 +#define SCE_RAKU_HEREDOC_Q 6 +#define SCE_RAKU_HEREDOC_QQ 7 +#define SCE_RAKU_STRING 8 +#define SCE_RAKU_STRING_Q 9 +#define SCE_RAKU_STRING_QQ 10 +#define SCE_RAKU_STRING_Q_LANG 11 +#define SCE_RAKU_STRING_VAR 12 +#define SCE_RAKU_REGEX 13 +#define SCE_RAKU_REGEX_VAR 14 +#define SCE_RAKU_ADVERB 15 +#define SCE_RAKU_NUMBER 16 +#define SCE_RAKU_PREPROCESSOR 17 +#define SCE_RAKU_OPERATOR 18 +#define SCE_RAKU_WORD 19 +#define SCE_RAKU_FUNCTION 20 +#define SCE_RAKU_IDENTIFIER 21 +#define SCE_RAKU_TYPEDEF 22 +#define SCE_RAKU_MU 23 +#define SCE_RAKU_POSITIONAL 24 +#define SCE_RAKU_ASSOCIATIVE 25 +#define SCE_RAKU_CALLABLE 26 +#define SCE_RAKU_GRAMMAR 27 +#define SCE_RAKU_CLASS 28 +#define SCE_FSHARP_DEFAULT 0 +#define SCE_FSHARP_KEYWORD 1 +#define SCE_FSHARP_KEYWORD2 2 +#define SCE_FSHARP_KEYWORD3 3 +#define SCE_FSHARP_KEYWORD4 4 +#define SCE_FSHARP_KEYWORD5 5 +#define SCE_FSHARP_IDENTIFIER 6 +#define SCE_FSHARP_QUOT_IDENTIFIER 7 +#define SCE_FSHARP_COMMENT 8 +#define SCE_FSHARP_COMMENTLINE 9 +#define SCE_FSHARP_PREPROCESSOR 10 +#define SCE_FSHARP_LINENUM 11 +#define SCE_FSHARP_OPERATOR 12 +#define SCE_FSHARP_NUMBER 13 +#define SCE_FSHARP_CHARACTER 14 +#define SCE_FSHARP_STRING 15 +#define SCE_FSHARP_VERBATIM 16 +#define SCE_FSHARP_QUOTATION 17 +#define SCE_FSHARP_ATTRIBUTE 18 +#define SCE_FSHARP_FORMAT_SPEC 19 +#define SCE_ASCIIDOC_DEFAULT 0 +#define SCE_ASCIIDOC_STRONG1 1 +#define SCE_ASCIIDOC_STRONG2 2 +#define SCE_ASCIIDOC_EM1 3 +#define SCE_ASCIIDOC_EM2 4 +#define SCE_ASCIIDOC_HEADER1 5 +#define SCE_ASCIIDOC_HEADER2 6 +#define SCE_ASCIIDOC_HEADER3 7 +#define SCE_ASCIIDOC_HEADER4 8 +#define SCE_ASCIIDOC_HEADER5 9 +#define SCE_ASCIIDOC_HEADER6 10 +#define SCE_ASCIIDOC_ULIST_ITEM 11 +#define SCE_ASCIIDOC_OLIST_ITEM 12 +#define SCE_ASCIIDOC_BLOCKQUOTE 13 +#define SCE_ASCIIDOC_LINK 14 +#define SCE_ASCIIDOC_CODEBK 15 +#define SCE_ASCIIDOC_PASSBK 16 +#define SCE_ASCIIDOC_COMMENT 17 +#define SCE_ASCIIDOC_COMMENTBK 18 +#define SCE_ASCIIDOC_LITERAL 19 +#define SCE_ASCIIDOC_LITERALBK 20 +#define SCE_ASCIIDOC_ATTRIB 21 +#define SCE_ASCIIDOC_ATTRIBVAL 22 +#define SCE_ASCIIDOC_MACRO 23 +#define SCE_GD_DEFAULT 0 +#define SCE_GD_COMMENTLINE 1 +#define SCE_GD_NUMBER 2 +#define SCE_GD_STRING 3 +#define SCE_GD_CHARACTER 4 +#define SCE_GD_WORD 5 +#define SCE_GD_TRIPLE 6 +#define SCE_GD_TRIPLEDOUBLE 7 +#define SCE_GD_CLASSNAME 8 +#define SCE_GD_FUNCNAME 9 +#define SCE_GD_OPERATOR 10 +#define SCE_GD_IDENTIFIER 11 +#define SCE_GD_COMMENTBLOCK 12 +#define SCE_GD_STRINGEOL 13 +#define SCE_GD_WORD2 14 +#define SCE_GD_ANNOTATION 15 +#define SCE_GD_NODEPATH 16 +#define SCE_TOML_DEFAULT 0 +#define SCE_TOML_COMMENT 1 +#define SCE_TOML_IDENTIFIER 2 +#define SCE_TOML_KEYWORD 3 +#define SCE_TOML_NUMBER 4 +#define SCE_TOML_TABLE 5 +#define SCE_TOML_KEY 6 +#define SCE_TOML_ERROR 7 +#define SCE_TOML_OPERATOR 8 +#define SCE_TOML_STRING_SQ 9 +#define SCE_TOML_STRING_DQ 10 +#define SCE_TOML_TRIPLE_STRING_SQ 11 +#define SCE_TOML_TRIPLE_STRING_DQ 12 +#define SCE_TOML_ESCAPECHAR 13 +#define SCE_TOML_DATETIME 14 +/* --Autogenerated -- end of section automatically generated from Scintilla.iface */ + +#endif diff --git a/src/lexilla/lexers/LexA68k.cxx b/src/lexilla/lexers/LexA68k.cxx new file mode 100644 index 000000000..6fdc8a56b --- /dev/null +++ b/src/lexilla/lexers/LexA68k.cxx @@ -0,0 +1,348 @@ +// Scintilla source code edit control +/** @file LexA68k.cxx + ** Lexer for Assembler, just for the MASM syntax + ** Written by Martial Demolins AKA Folco + **/ +// Copyright 2010 Martial Demolins +// The License.txt file describes the conditions under which this software +// may be distributed. + + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + + +// Return values for GetOperatorType +#define NO_OPERATOR 0 +#define OPERATOR_1CHAR 1 +#define OPERATOR_2CHAR 2 + + +/** + * IsIdentifierStart + * + * Return true if the given char is a valid identifier first char + */ + +static inline bool IsIdentifierStart (const int ch) +{ + return (isalpha(ch) || (ch == '_') || (ch == '\\')); +} + + +/** + * IsIdentifierChar + * + * Return true if the given char is a valid identifier char + */ + +static inline bool IsIdentifierChar (const int ch) +{ + return (isalnum(ch) || (ch == '_') || (ch == '@') || (ch == ':') || (ch == '.')); +} + + +/** + * GetOperatorType + * + * Return: + * NO_OPERATOR if char is not an operator + * OPERATOR_1CHAR if the operator is one char long + * OPERATOR_2CHAR if the operator is two chars long + */ + +static inline int GetOperatorType (const int ch1, const int ch2) +{ + int OpType = NO_OPERATOR; + + if ((ch1 == '+') || (ch1 == '-') || (ch1 == '*') || (ch1 == '/') || (ch1 == '#') || + (ch1 == '(') || (ch1 == ')') || (ch1 == '~') || (ch1 == '&') || (ch1 == '|') || (ch1 == ',')) + OpType = OPERATOR_1CHAR; + + else if ((ch1 == ch2) && (ch1 == '<' || ch1 == '>')) + OpType = OPERATOR_2CHAR; + + return OpType; +} + + +/** + * IsBin + * + * Return true if the given char is 0 or 1 + */ + +static inline bool IsBin (const int ch) +{ + return (ch == '0') || (ch == '1'); +} + + +/** + * IsDoxygenChar + * + * Return true if the char may be part of a Doxygen keyword + */ + +static inline bool IsDoxygenChar (const int ch) +{ + return isalpha(ch) || (ch == '$') || (ch == '[') || (ch == ']') || (ch == '{') || (ch == '}'); +} + + +/** + * ColouriseA68kDoc + * + * Main function, which colourises a 68k source + */ + +static void ColouriseA68kDoc (Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], Accessor &styler) +{ + // Used to buffer a string, to be able to compare it using built-in functions + char Buffer[100]; + + + // Used to know the length of an operator + int OpType; + + + // Get references to keywords lists + WordList &cpuInstruction = *keywordlists[0]; + WordList ®isters = *keywordlists[1]; + WordList &directive = *keywordlists[2]; + WordList &extInstruction = *keywordlists[3]; + WordList &alert = *keywordlists[4]; + WordList &doxygenKeyword = *keywordlists[5]; + + + // Instanciate a context for our source + StyleContext sc(startPos, length, initStyle, styler); + + + /************************************************************ + * + * Parse the source + * + ************************************************************/ + + for ( ; sc.More(); sc.Forward()) + { + /************************************************************ + * + * A style always terminates at the end of a line, even for + * comments (no multi-lines comments) + * + ************************************************************/ + if (sc.atLineStart) { + sc.SetState(SCE_A68K_DEFAULT); + } + + + /************************************************************ + * + * If we are not in "default style", check if the style continues + * In this case, we just have to loop + * + ************************************************************/ + + if (sc.state != SCE_A68K_DEFAULT) + { + if ( ((sc.state == SCE_A68K_NUMBER_DEC) && isdigit(sc.ch)) // Decimal number + || ((sc.state == SCE_A68K_NUMBER_BIN) && IsBin(sc.ch)) // Binary number + || ((sc.state == SCE_A68K_NUMBER_HEX) && isxdigit(sc.ch)) // Hexa number + || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Macro argument + || ((sc.state == SCE_A68K_STRING1) && (sc.ch != '\'')) // String single-quoted + || ((sc.state == SCE_A68K_STRING2) && (sc.ch != '\"')) // String double-quoted + || ((sc.state == SCE_A68K_MACRO_DECLARATION) && IsIdentifierChar(sc.ch)) // Macro declaration (or global label, we don't know at this point) + || ((sc.state == SCE_A68K_IDENTIFIER) && IsIdentifierChar(sc.ch)) // Identifier + || ((sc.state == SCE_A68K_LABEL) && IsIdentifierChar(sc.ch)) // Label (local) + || ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && IsDoxygenChar(sc.ch)) // Doxygen keyword + || ((sc.state == SCE_A68K_COMMENT_SPECIAL) && isalpha(sc.ch)) // Alert + || ((sc.state == SCE_A68K_COMMENT) && !isalpha(sc.ch) && (sc.ch != '\\'))) // Normal comment + { + continue; + } + + /************************************************************ + * + * Check if current state terminates + * + ************************************************************/ + + // Strings: include terminal ' or " in the current string by skipping it + if ((sc.state == SCE_A68K_STRING1) || (sc.state == SCE_A68K_STRING2)) { + sc.Forward(); + } + + + // If a macro declaration was terminated with ':', it was a label + else if ((sc.state == SCE_A68K_MACRO_DECLARATION) && (sc.chPrev == ':')) { + sc.ChangeState(SCE_A68K_LABEL); + } + + + // If it wasn't a Doxygen keyword, change it to normal comment + else if (sc.state == SCE_A68K_COMMENT_DOXYGEN) { + sc.GetCurrent(Buffer, sizeof(Buffer)); + if (!doxygenKeyword.InList(Buffer)) { + sc.ChangeState(SCE_A68K_COMMENT); + } + sc.SetState(SCE_A68K_COMMENT); + continue; + } + + + // If it wasn't an Alert, change it to normal comment + else if (sc.state == SCE_A68K_COMMENT_SPECIAL) { + sc.GetCurrent(Buffer, sizeof(Buffer)); + if (!alert.InList(Buffer)) { + sc.ChangeState(SCE_A68K_COMMENT); + } + // Reset style to normal comment, or to Doxygen keyword if it begins with '\' + if (sc.ch == '\\') { + sc.SetState(SCE_A68K_COMMENT_DOXYGEN); + } + else { + sc.SetState(SCE_A68K_COMMENT); + } + continue; + } + + + // If we are in a comment, it's a Doxygen keyword or an Alert + else if (sc.state == SCE_A68K_COMMENT) { + if (sc.ch == '\\') { + sc.SetState(SCE_A68K_COMMENT_DOXYGEN); + } + else { + sc.SetState(SCE_A68K_COMMENT_SPECIAL); + } + continue; + } + + + // Check if we are at the end of an identifier + // In this case, colourise it if was a keyword. + else if ((sc.state == SCE_A68K_IDENTIFIER) && !IsIdentifierChar(sc.ch)) { + sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context + if (cpuInstruction.InList(Buffer)) { // And check if it belongs to a keyword list + sc.ChangeState(SCE_A68K_CPUINSTRUCTION); + } + else if (extInstruction.InList(Buffer)) { + sc.ChangeState(SCE_A68K_EXTINSTRUCTION); + } + else if (registers.InList(Buffer)) { + sc.ChangeState(SCE_A68K_REGISTER); + } + else if (directive.InList(Buffer)) { + sc.ChangeState(SCE_A68K_DIRECTIVE); + } + } + + // All special contexts are now handled.Come back to default style + sc.SetState(SCE_A68K_DEFAULT); + } + + + /************************************************************ + * + * Check if we must enter a new state + * + ************************************************************/ + + // Something which begins at the beginning of a line, and with + // - '\' + an identifier start char, or + // - '\\@' + an identifier start char + // is a local label (second case is used for macro local labels). We set it already as a label, it can't be a macro/equ declaration + if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.chNext) && (sc.ch == '\\')) { + sc.SetState(SCE_A68K_LABEL); + } + + if (sc.atLineStart && (sc.ch < 0x80) && (sc.ch == '\\') && (sc.chNext == '\\')) { + sc.Forward(2); + if ((sc.ch == '@') && IsIdentifierStart(sc.chNext)) { + sc.ChangeState(SCE_A68K_LABEL); + sc.SetState(SCE_A68K_LABEL); + } + } + + // Label and macro identifiers start at the beginning of a line + // We set both as a macro id, but if it wasn't one (':' at the end), + // it will be changed as a label. + if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { + sc.SetState(SCE_A68K_MACRO_DECLARATION); + } + else if ((sc.ch < 0x80) && (sc.ch == ';')) { // Default: alert in a comment. If it doesn't match + sc.SetState(SCE_A68K_COMMENT); // with an alert, it will be toggle to a normal comment + } + else if ((sc.ch < 0x80) && isdigit(sc.ch)) { // Decimal numbers haven't prefix + sc.SetState(SCE_A68K_NUMBER_DEC); + } + else if ((sc.ch < 0x80) && (sc.ch == '%')) { // Binary numbers are prefixed with '%' + sc.SetState(SCE_A68K_NUMBER_BIN); + } + else if ((sc.ch < 0x80) && (sc.ch == '$')) { // Hexadecimal numbers are prefixed with '$' + sc.SetState(SCE_A68K_NUMBER_HEX); + } + else if ((sc.ch < 0x80) && (sc.ch == '\'')) { // String (single-quoted) + sc.SetState(SCE_A68K_STRING1); + } + else if ((sc.ch < 0x80) && (sc.ch == '\"')) { // String (double-quoted) + sc.SetState(SCE_A68K_STRING2); + } + else if ((sc.ch < 0x80) && (sc.ch == '\\') && (isdigit(sc.chNext))) { // Replacement symbols in macro are prefixed with '\' + sc.SetState(SCE_A68K_MACRO_ARG); + } + else if ((sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { // An identifier: constant, label, etc... + sc.SetState(SCE_A68K_IDENTIFIER); + } + else { + if (sc.ch < 0x80) { + OpType = GetOperatorType(sc.ch, sc.chNext); // Check if current char is an operator + if (OpType != NO_OPERATOR) { + sc.SetState(SCE_A68K_OPERATOR); + if (OpType == OPERATOR_2CHAR) { // Check if the operator is 2 bytes long + sc.ForwardSetState(SCE_A68K_OPERATOR); // (>> or <<) + } + } + } + } + } // End of for() + sc.Complete(); +} + + +// Names of the keyword lists + +static const char * const a68kWordListDesc[] = +{ + "CPU instructions", + "Registers", + "Directives", + "Extended instructions", + "Comment special words", + "Doxygen keywords", + 0 +}; + +extern const LexerModule lmA68k(SCLEX_A68K, ColouriseA68kDoc, "a68k", 0, a68kWordListDesc); diff --git a/src/lexilla/lexers/LexAPDL.cxx b/src/lexilla/lexers/LexAPDL.cxx new file mode 100644 index 000000000..7a618876c --- /dev/null +++ b/src/lexilla/lexers/LexAPDL.cxx @@ -0,0 +1,260 @@ +// Scintilla source code edit control +/** @file LexAPDL.cxx + ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus. + ** By Hadar Raz. + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || ch == '_')); +} + +static inline bool IsAnOperator(char ch) { + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '$' || ch == ':' || ch == '%') + return true; + return false; +} + +static void ColouriseAPDLDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + int stringStart = ' '; + + WordList &processors = *keywordlists[0]; + WordList &commands = *keywordlists[1]; + WordList &slashcommands = *keywordlists[2]; + WordList &starcommands = *keywordlists[3]; + WordList &arguments = *keywordlists[4]; + WordList &functions = *keywordlists[5]; + + // Do not leak onto next line + initStyle = SCE_APDL_DEFAULT; + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + // Determine if the current state should terminate. + if (sc.state == SCE_APDL_NUMBER) { + if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_COMMENTBLOCK) { + if (sc.atLineEnd) { + if (sc.ch == '\r') { + sc.Forward(); + } + sc.ForwardSetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_STRING) { + if (sc.atLineEnd) { + sc.SetState(SCE_APDL_DEFAULT); + } else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) { + sc.ForwardSetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_WORD) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (processors.InList(s)) { + sc.ChangeState(SCE_APDL_PROCESSOR); + } else if (slashcommands.InList(s)) { + sc.ChangeState(SCE_APDL_SLASHCOMMAND); + } else if (starcommands.InList(s)) { + sc.ChangeState(SCE_APDL_STARCOMMAND); + } else if (commands.InList(s)) { + sc.ChangeState(SCE_APDL_COMMAND); + } else if (arguments.InList(s)) { + sc.ChangeState(SCE_APDL_ARGUMENT); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_APDL_FUNCTION); + } + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_OPERATOR) { + if (!IsAnOperator(static_cast(sc.ch))) { + sc.SetState(SCE_APDL_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_APDL_DEFAULT) { + if (sc.ch == '!' && sc.chNext == '!') { + sc.SetState(SCE_APDL_COMMENTBLOCK); + } else if (sc.ch == '!') { + sc.SetState(SCE_APDL_COMMENT); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_APDL_NUMBER); + } else if (sc.ch == '\'' || sc.ch == '\"') { + sc.SetState(SCE_APDL_STRING); + stringStart = sc.ch; + } else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) { + sc.SetState(SCE_APDL_WORD); + } else if (IsAnOperator(static_cast(sc.ch))) { + sc.SetState(SCE_APDL_OPERATOR); + } + } + } + sc.Complete(); +} + +//------------------------------------------------------------------------------ +// 06-27-07 Sergio Lucato +// - Included code folding for Ansys APDL lexer +// - Copyied from LexBasic.cxx and modified for APDL +//------------------------------------------------------------------------------ + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int CheckAPDLFoldPoint(char const *token, int &level) { + if (!strcmp(token, "*if") || + !strcmp(token, "*do") || + !strcmp(token, "*dowhile") ) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "*endif") || + !strcmp(token, "*enddo") ) { + return -1; + } + return 0; +} + +static void FoldAPDLDoc(Sci_PositionU startPos, Sci_Position length, int, + WordList *[], Accessor &styler) { + + Sci_Position line = styler.GetLine(startPos); + int level = styler.LevelAt(line); + int go = 0, done = 0; + Sci_Position endPos = startPos + length; + char word[256]; + int wordlen = 0; + Sci_Position i; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // Scan for tokens at the start of the line (they may include + // whitespace, for tokens like "End Function" + for (i = startPos; i < endPos; i++) { + int c = styler.SafeGetCharAt(i); + if (!done && !go) { + if (wordlen) { // are we scanning a token already? + word[wordlen] = static_cast(LowerCase(c)); + if (!IsIdentifier(c)) { // done with token + word[wordlen] = '\0'; + go = CheckAPDLFoldPoint(word, level); + if (!go) { + // Treat any whitespace as single blank, for + // things like "End Function". + if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { + word[wordlen] = ' '; + if (wordlen < 255) + wordlen++; + } + else // done with this line + done = 1; + } + } else if (wordlen < 255) { + wordlen++; + } + } else { // start scanning at first non-whitespace character + if (!IsSpace(c)) { + if (IsIdentifier(c)) { + word[0] = static_cast(LowerCase(c)); + wordlen = 1; + } else // done with this line + done = 1; + } + } + } + if (c == '\n') { // line end + if (!done && wordlen == 0 && foldCompact) // line was only space + level |= SC_FOLDLEVELWHITEFLAG; + if (level != styler.LevelAt(line)) + styler.SetLevel(line, level); + level += go; + line++; + // reset state + wordlen = 0; + level &= ~SC_FOLDLEVELHEADERFLAG; + level &= ~SC_FOLDLEVELWHITEFLAG; + go = 0; + done = 0; + } + } +} + +static const char * const apdlWordListDesc[] = { + "processors", + "commands", + "slashommands", + "starcommands", + "arguments", + "functions", + 0 +}; + +extern const LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc); diff --git a/src/lexilla/lexers/LexASY.cxx b/src/lexilla/lexers/LexASY.cxx new file mode 100644 index 000000000..f9e62e43d --- /dev/null +++ b/src/lexilla/lexers/LexASY.cxx @@ -0,0 +1,275 @@ +// Scintilla source code edit control +// @file LexASY.cxx +//Author: instanton (email: soft_share126com) +// This lexer is for the Asymptote vector graphics language +// https://en.wikipedia.org/wiki/Asymptote_(vector_graphics_language) +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static void ColouriseAsyDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + int visibleChars = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + if (sc.state == SCE_ASY_STRING) { + sc.SetState(SCE_ASY_STRING); + } + visibleChars = 0; + } + + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } +// continuationLine = true; + continue; + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_ASY_OPERATOR: + sc.SetState(SCE_ASY_DEFAULT); + break; + case SCE_ASY_NUMBER: + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_ASY_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_ASY_WORD2); + } + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ASY_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ASY_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ASY_DEFAULT) { + if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + sc.SetState(SCE_ASY_IDENTIFIER); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_ASY_COMMENT); + sc.Forward(); // + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_ASY_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ASY_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ASY_CHARACTER); + } else if (sc.ch == '#' && visibleChars == 0) { + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_ASY_DEFAULT); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_ASY_OPERATOR); + } + } + + } + sc.Complete(); +} + +static bool IsAsyCommentStyle(int style) { + return style == SCE_ASY_COMMENT; +} + + +static inline bool isASYidentifier(int ch) { + return + ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ; +} + +static int ParseASYWord(Sci_PositionU pos, Accessor &styler, char *word) +{ + int length=0; + char ch=styler.SafeGetCharAt(pos); + *word=0; + + while(isASYidentifier(ch) && length<100){ + word[length]=ch; + length++; + ch=styler.SafeGetCharAt(pos+length); + } + word[length]=0; + return length; +} + +static bool IsASYDrawingLine(Sci_Position line, Accessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + + Sci_Position startpos = pos; + char buffer[100]=""; + + while (startpos 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsAsyCommentStyle(style)) { + if (!IsAsyCommentStyle(stylePrev) && (stylePrev != SCE_ASY_COMMENTLINEDOC)) { + levelNext++; + } else if (!IsAsyCommentStyle(styleNext) && (styleNext != SCE_ASY_COMMENTLINEDOC) && !atEOL) { + levelNext--; + } + } + if (style == SCE_ASY_OPERATOR) { + if (ch == '{') { + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + + if (atEOL && IsASYDrawingLine(lineCurrent, styler)){ + if (lineCurrent==0 && IsASYDrawingLine(lineCurrent + 1, styler)) + levelNext++; + else if (lineCurrent!=0 && !IsASYDrawingLine(lineCurrent - 1, styler) + && IsASYDrawingLine(lineCurrent + 1, styler) + ) + levelNext++; + else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) && + !IsASYDrawingLine(lineCurrent+1, styler)) + levelNext--; + } + + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!IsASpace(ch)) + visibleChars++; + } +} + +static const char * const asyWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + 0, + }; + +extern const LexerModule lmASY(SCLEX_ASYMPTOTE, ColouriseAsyDoc, "asy", FoldAsyDoc, asyWordLists); diff --git a/src/lexilla/lexers/LexAU3.cxx b/src/lexilla/lexers/LexAU3.cxx new file mode 100644 index 000000000..4813a62c2 --- /dev/null +++ b/src/lexilla/lexers/LexAU3.cxx @@ -0,0 +1,911 @@ +// Scintilla source code edit control +// @file LexAU3.cxx +// Lexer for AutoIt3 https://www.autoitscript.com/site/ +// by Jos van der Zande, jvdzande@yahoo.com +// +// Changes: +// March 28, 2004 - Added the standard Folding code +// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting +// Fixed Number highlighting +// Changed default isoperator to IsAOperator to have a better match to AutoIt3 +// Fixed "#comments_start" -> "#comments-start" +// Fixed "#comments_end" -> "#comments-end" +// Fixed Sendkeys in Strings when not terminated with } +// Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} +// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. +// Added logic for #include to treat the <> as string +// Added underscore to IsAOperator. +// May 17, 2004 - Changed the folding logic from indent to keyword folding. +// Added Folding logic for blocks of single-commentlines or commentblock. +// triggered by: fold.comment=1 +// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 +// Added Special for #region - #endregion syntax highlight and folding. +// May 30, 2004 - Fixed issue with continuation lines on If statements. +// June 5, 2004 - Added comma to Operators for better readability. +// Added fold.compact support set with fold.compact=1 +// Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 +// it will now only happen when fold.comment=2. +// Sep 5, 2004 - Added logic to handle colourizing words on the last line. +// Typed Characters now show as "default" till they match any table. +// Oct 10, 2004 - Added logic to show Comments in "Special" directives. +// Nov 1, 2004 - Added better testing for Numbers supporting x and e notation. +// Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting. +// Jan 10, 2005 - Added Abbreviations Keyword used for expansion +// Mar 24, 2005 - Updated Abbreviations Keywords to fix when followed by Operator. +// Apr 18, 2005 - Updated #CE/#Comment-End logic to take a linecomment ";" into account +// - Added folding support for With...EndWith +// - Added support for a DOT in variable names +// - Fixed Underscore in CommentBlock +// May 23, 2005 - Fixed the SentKey lexing in case of a missing } +// Aug 11, 2005 - Fixed possible bug with s_save length > 100. +// Aug 23, 2005 - Added Switch/endswitch support to the folding logic. +// Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys. +// Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions. +// Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF) +// Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color. +// Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL. +// Jul 26, 2007 - Fixed #endregion undetected bug. +// +// Copyright for Scintilla: 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +// Scintilla source code edit control + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsTypeCharacter(const int ch) +{ + return ch == '$'; +} +static inline bool IsAWordChar(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); +} + +static inline bool IsAOperator(char ch) { + if (IsASCII(ch) && isalnum(ch)) + return false; + if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || + ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' ) + return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetSendKey() filters the portion before and after a/multiple space(s) +// and return the first portion to be looked-up in the table +// also check if the second portion is valid... (up,down.on.off,toggle or a number) +/////////////////////////////////////////////////////////////////////////////// + +static int GetSendKey(const char *szLine, char *szKey) +{ + int nFlag = 0; + int nStartFound = 0; + int nKeyPos = 0; + int nSpecPos= 0; + int nSpecNum= 1; + int nPos = 0; + char cTemp; + char szSpecial[100]; + + // split the portion of the sendkey in the part before and after the spaces + while ( ( (cTemp = szLine[nPos]) != '\0')) + { + // skip leading Ctrl/Shift/Alt state + if (cTemp == '{') { + nStartFound = 1; + } + // + if (nStartFound == 1) { + if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space + { + nFlag = 1; + // Add } to the end of the first bit for table lookup later. + szKey[nKeyPos++] = '}'; + } + else if (cTemp == ' ') + { + // skip other spaces + } + else if (nFlag == 0) + { + // save first portion into var till space or } is hit + szKey[nKeyPos++] = cTemp; + } + else if ((nFlag == 1) && (cTemp != '}')) + { + // Save second portion into var... + szSpecial[nSpecPos++] = cTemp; + // check if Second portion is all numbers for repeat fuction + if (isdigit(cTemp) == false) {nSpecNum = 0;} + } + } + nPos++; // skip to next char + + } // End While + + + // Check if the second portion is either a number or one of these keywords + szKey[nKeyPos] = '\0'; + szSpecial[nSpecPos] = '\0'; + if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || + strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || + strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) + { + nFlag = 0; + } + else + { + nFlag = 1; + } + return nFlag; // 1 is bad, 0 is good + +} // GetSendKey() + +// +// Routine to check the last "none comment" character on a line to see if its a continuation +// +static bool IsContinuationLine(Sci_PositionU szLine, Accessor &styler) +{ + Sci_Position nsPos = styler.LineStart(szLine); + Sci_Position nePos = styler.LineStart(szLine+1) - 2; + //int stylech = styler.StyleAt(nsPos); + while (nsPos < nePos) + { + //stylech = styler.StyleAt(nePos); + int stylech = styler.StyleAt(nsPos); + if (!(stylech == SCE_AU3_COMMENT)) { + char ch = styler.SafeGetCharAt(nePos); + if (!isspacechar(ch)) { + if (ch == '_') + return true; + else + return false; + } + } + nePos--; // skip to next char + } // End While + return false; +} // IsContinuationLine() + +// +// syntax highlighting logic +static void ColouriseAU3Doc(Sci_PositionU startPos, + Sci_Position length, int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + // find the first previous line without continuation character at the end + Sci_Position lineCurrent = styler.GetLine(startPos); + Sci_Position s_startPos = startPos; + // When not inside a Block comment: find First line without _ + if (!(initStyle==SCE_AU3_COMMENTBLOCK)) { + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); // get start position + initStyle = 0; // reset the start style to 0 + } + } + // Set the new length to include it from the start and set the start position + length = length + s_startPos - startPos; // correct the total length to process + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + char si; // string indicator "=1 '=2 + char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 + char ci; // comment indicator 0=not linecomment(;) + char s_save[100] = ""; + si=0; + ni=0; + ci=0; + //$$$ + for (; sc.More(); sc.Forward()) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + // ********************************************** + // save the total current word for eof processing + if (IsAWordChar(sc.ch) || sc.ch == '}') + { + strcpy(s_save,s); + int tp = static_cast(strlen(s_save)); + if (tp < 99) { + s_save[tp] = static_cast(tolower(sc.ch)); + s_save[tp+1] = '\0'; + } + } + // ********************************************** + // + switch (sc.state) + { + case SCE_AU3_COMMENTBLOCK: + { + //Reset at line end + if (sc.atLineEnd) { + ci=0; + if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) { + if (sc.atLineEnd) + sc.SetState(SCE_AU3_DEFAULT); + else + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + //skip rest of line when a ; is encountered + if (sc.chPrev == ';') { + ci=2; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + // skip rest of the line + if (ci==2) + break; + // check when first character is detected on the line + if (ci==0) { + if (IsAWordStart(static_cast(sc.ch)) || IsAOperator(static_cast(sc.ch))) { + ci=1; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) { + if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) + sc.SetState(SCE_AU3_COMMENT); // set to comment line for the rest of the line + else + ci=2; // line doesn't begin with #CE so skip the rest of the line + } + break; + } + case SCE_AU3_COMMENT: + { + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_OPERATOR: + { + // check if its a COMobject + if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_COMOBJ); + } + else { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_SPECIAL: + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_KEYWORD: + { + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0)))) + { + if (!IsTypeCharacter(sc.ch)) + { + if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + break; + } + else if (keywords.InList(s)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords2.InList(s)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords3.InList(s)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords5.InList(s)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_DEFAULT); + if (strcmp(s, "#include")== 0) + { + si = 3; // use to determine string start for #inlude <> + } + } + else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if ((keywords7.InList(s)) && (!IsAOperator(static_cast(sc.ch)))) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords8.InList(s)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (strcmp(s, "_") == 0) { + sc.ChangeState(SCE_AU3_OPERATOR); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + } + if (sc.atLineEnd) { + sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_NUMBER: + { + // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3 + // + // test for Hex notation + if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0) + { + ni = 2; + break; + } + // test for E notation + if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1) + { + ni = 3; + break; + } + // Allow Hex characters inside hex numeric strings + if ((ni == 2) && + (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' || + sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' )) + { + break; + } + // test for 1 dec point only + if (sc.ch == '.') + { + if (ni==0) + { + ni=1; + } + else + { + ni=9; + } + break; + } + // end of numeric string ? + if (!(IsADigit(sc.ch))) + { + if (ni==9) + { + sc.ChangeState(SCE_AU3_DEFAULT); + } + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_VARIABLE: + { + // Check if its a COMObject + if (sc.ch == '.' && !IsADigit(sc.chNext)) { + sc.SetState(SCE_AU3_OPERATOR); + } + else if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_COMOBJ: + { + if (!(IsAWordChar(sc.ch))) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_STRING: + { + // check for " to end a double qouted string or + // check for ' to end a single qouted string + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) + { + sc.ForwardSetState(SCE_AU3_DEFAULT); + si=0; + break; + } + if (sc.atLineEnd) + { + si=0; + // at line end and not found a continuation char then reset to default + Sci_Position lineCurrent = styler.GetLine(sc.currentPos); + if (!IsContinuationLine(lineCurrent,styler)) + { + sc.SetState(SCE_AU3_DEFAULT); + break; + } + } + // find Sendkeys in a STRING + if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) { + sc.SetState(SCE_AU3_SENT);} + break; + } + + case SCE_AU3_SENT: + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + else + { + // check if the start is a valid SendKey start + Sci_Position nPos = 0; + int nState = 1; + char cTemp; + while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) + { + if (cTemp == '{' && nState == 1) + { + nState = 2; + } + if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' )) + { + nState = 0; + } + nPos++; + } + //Verify characters infront of { ... if not assume regular string + if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + // If invalid character found then assume its a regular string + if (nState == 0) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + si = 0; // reset string indicator + } + //* check in next characters following a sentkey are again a sent key + // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{} + if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) { + sc.SetState(SCE_AU3_SENT);} + // check to see if the string ended... + // Sendkey string isn't complete but the string ended.... + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'')) + { + sc.ChangeState(SCE_AU3_STRING); + sc.ForwardSetState(SCE_AU3_DEFAULT); + } + break; + } + } //switch (sc.state) + + // Determine if a new state should be entered: + + if (sc.state == SCE_AU3_DEFAULT) + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);} + else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} + //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include + else if (sc.ch == '\"') { + sc.SetState(SCE_AU3_STRING); + si = 1; } + else if (sc.ch == '\'') { + sc.SetState(SCE_AU3_STRING); + si = 2; } + else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) + { + sc.SetState(SCE_AU3_NUMBER); + ni = 0; + } + else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} + else if (IsAOperator(static_cast(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + } + } //for (; sc.More(); sc.Forward()) + + //************************************* + // Colourize the last word correctly + //************************************* + if (sc.state == SCE_AU3_KEYWORD) + { + if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + else if (keywords.InList(s_save)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_KEYWORD); + } + else if (keywords2.InList(s_save)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_FUNCTION); + } + else if (keywords3.InList(s_save)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_MACRO); + } + else if (keywords5.InList(s_save)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_PREPROCESSOR); + } + else if (keywords6.InList(s_save)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if (keywords7.InList(s_save) && sc.atLineEnd) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_EXPAND); + } + else if (keywords8.InList(s_save)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_UDF); + } + else { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + if (sc.state == SCE_AU3_SENT) + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s_save,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + } + } + //************************************* + sc.Complete(); +} + +// +static bool IsStreamCommentStyle(int style) { + return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; +} + +// +// Routine to find first none space on the current line and return its Style +// needed for comment lines not starting on pos 1 +static int GetStyleFirstWord(Sci_PositionU szLine, Accessor &styler) +{ + Sci_Position nsPos = styler.LineStart(szLine); + Sci_Position nePos = styler.LineStart(szLine+1) - 1; + while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) + { + nsPos++; // skip to next char + + } // End While + return styler.StyleAt(nsPos); + +} // GetStyleFirstWord() + + +// +static void FoldAU3Doc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) +{ + Sci_Position endPos = startPos + length; + // get settings from the config files for folding comments and preprocessor lines + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + // Backtrack to previous line in case need to fix its fold status + Sci_Position lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + // vars for style of previous/current/next lines + int style = GetStyleFirstWord(lineCurrent,styler); + int stylePrev = 0; + // find the first previous line without continuation character at the end + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + if (lineCurrent > 0) { + stylePrev = GetStyleFirstWord(lineCurrent-1,styler); + } + // vars for getting first word to check for keywords + bool FirstWordStart = false; + bool FirstWordEnd = false; + char szKeyword[11]=""; + int szKeywordlen = 0; + char szThen[5]=""; + int szThenlen = 0; + bool ThenFoundLast = false; + // var for indentlevel + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + // + int visibleChars = 0; + char chNext = styler.SafeGetCharAt(startPos); + char chPrev = ' '; + // + for (Sci_Position i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + if (IsAWordChar(ch)) { + visibleChars++; + } + // get the syle for the current character neede to check in comment + int stylech = styler.StyleAt(i); + // get first word for the line for indent check max 9 characters + if (FirstWordStart && (!(FirstWordEnd))) { + if (!IsAWordChar(ch)) { + FirstWordEnd = true; + szKeyword[szKeywordlen] = '\0'; + } + else { + if (szKeywordlen < 10) { + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + } + // start the capture of the first word + if (!(FirstWordStart)) { + if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { + FirstWordStart = true; + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + // only process this logic when not in comment section + if (!(stylech == SCE_AU3_COMMENT)) { + if (ThenFoundLast) { + if (IsAWordChar(ch)) { + ThenFoundLast = false; + } + } + // find out if the word "then" is the last on a "if" line + if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { + if (szThenlen == 4) { + szThen[0] = szThen[1]; + szThen[1] = szThen[2]; + szThen[2] = szThen[3]; + szThen[3] = static_cast(tolower(ch)); + if (strcmp(szThen,"then") == 0 ) { + ThenFoundLast = true; + } + } + else { + szThen[szThenlen++] = static_cast(tolower(ch)); + if (szThenlen == 5) { + szThen[4] = '\0'; + } + } + } + } + // End of Line found so process the information + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + // ************************** + // Folding logic for Keywords + // ************************** + // if a keyword is found on the current line and the line doesn't end with _ (continuation) + // and we are not inside a commentblock. + if (szKeywordlen > 0 && (!(chPrev == '_')) && + ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { + szKeyword[szKeywordlen] = '\0'; + // only fold "if" last keyword is "then" (else its a one line if) + if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { + levelNext++; + } + // create new fold for these words + if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || + strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| + strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) { + levelNext++; + } + // create double Fold for select&switch because Case will subtract one of the current level + if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) { + levelNext++; + levelNext++; + } + // end the fold for these words before the current line + if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || + strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || + strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){ + levelNext--; + levelCurrent--; + } + // end the fold for these words before the current line and Start new fold + if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || + strcmp(szKeyword,"elseif") == 0 ) { + levelCurrent--; + } + // end the double fold for this word before the current line + if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) { + levelNext--; + levelNext--; + levelCurrent--; + levelCurrent--; + } + // end the fold for these words on the current line + if (strcmp(szKeyword,"#endregion") == 0 ) { + levelNext--; + } + } + // Preprocessor and Comment folding + int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); + // ************************************* + // Folding logic for preprocessor blocks + // ************************************* + // process preprosessor line + if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { + if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext--; + } + } + // ********************************* + // Folding logic for Comment blocks + // ********************************* + if (foldComment && IsStreamCommentStyle(style)) { + // Start of a comment block + if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENT) + && stylePrev == SCE_AU3_COMMENT + && style == SCE_AU3_COMMENT) { + levelNext--; + } + // fold till the one but last line for Blockcomment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENTBLOCK) + && style == SCE_AU3_COMMENTBLOCK) { + levelNext--; + levelCurrent--; + } + } + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + // reset values for the next line + lineCurrent++; + stylePrev = style; + style = styleNext; + levelCurrent = levelNext; + visibleChars = 0; + // if the last character is an Underscore then don't reset since the line continues on the next line. + if (!(chPrev == '_')) { + szKeywordlen = 0; + szThenlen = 0; + FirstWordStart = false; + FirstWordEnd = false; + ThenFoundLast = false; + } + } + // save the last processed character + if (!isspacechar(ch)) { + chPrev = ch; + visibleChars++; + } + } +} + + +// + +static const char * const AU3WordLists[] = { + "#autoit keywords", + "#autoit functions", + "#autoit macros", + "#autoit Sent keys", + "#autoit Pre-processors", + "#autoit Special", + "#autoit Expand", + "#autoit UDF", + 0 +}; +extern const LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists); diff --git a/src/lexilla/lexers/LexAVE.cxx b/src/lexilla/lexers/LexAVE.cxx new file mode 100644 index 000000000..8a90d2123 --- /dev/null +++ b/src/lexilla/lexers/LexAVE.cxx @@ -0,0 +1,232 @@ +// SciTE - Scintilla based Text Editor +/** @file LexAVE.cxx + ** Lexer for Avenue. + ** + ** Written by Alexey Yutkin . + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} +static inline bool IsEnumChar(const int ch) { + return (ch < 0x80) && (isalnum(ch)|| ch == '_'); +} +static inline bool IsANumberChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' ); +} + +inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +inline bool isAveOperator(char ch) { + if (IsASCII(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || + ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || + ch == '.' ) + return true; + return false; +} + +static void ColouriseAveDoc( + Sci_PositionU startPos, + Sci_Position length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + + // Do not leak onto next line + if (initStyle == SCE_AVE_STRINGEOL) { + initStyle = SCE_AVE_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + Sci_Position currentLine = styler.GetLine(sc.currentPos); + styler.SetLineState(currentLine, 0); + } + if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) { + // Prevent SCE_AVE_STRINGEOL from leaking back to previous line + sc.SetState(SCE_AVE_STRING); + } + + + // Determine if the current state should terminate. + if (sc.state == SCE_AVE_OPERATOR) { + sc.SetState(SCE_AVE_DEFAULT); + } else if (sc.state == SCE_AVE_NUMBER) { + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_ENUM) { + if (!IsEnumChar(sc.ch)) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + //sc.GetCurrent(s, sizeof(s)); + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVE_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_AVE_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_AVE_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_AVE_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_AVE_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AVE_WORD6); + } + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_AVE_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_AVE_STRINGEOL); + sc.ForwardSetState(SCE_AVE_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_AVE_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_AVE_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_AVE_IDENTIFIER); + } else if (sc.Match('\"')) { + sc.SetState(SCE_AVE_STRING); + } else if (sc.Match('\'')) { + sc.SetState(SCE_AVE_COMMENT); + sc.Forward(); + } else if (isAveOperator(static_cast(sc.ch))) { + sc.SetState(SCE_AVE_OPERATOR); + } else if (sc.Match('#')) { + sc.SetState(SCE_AVE_ENUM); + sc.Forward(); + } + } + } + sc.Complete(); +} + +static void FoldAveDoc(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[], + Accessor &styler) { + Sci_PositionU lengthDoc = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = static_cast(tolower(styler[startPos])); + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int styleNext = styler.StyleAt(startPos); + char s[10] = ""; + + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = static_cast(tolower(chNext)); + chNext = static_cast(tolower(styler.SafeGetCharAt(i + 1))); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_AVE_WORD) { + if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') { + for (unsigned int j = 0; j < 6; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = static_cast(tolower(styler[i + j])); + s[j + 1] = '\0'; + } + + if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) { + levelCurrent++; + } + if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) { + // Normally "elseif" and "then" will be on the same line and will cancel + // each other out. // As implemented, this does not support fold.at.else. + levelCurrent--; + } + } + } else if (style == SCE_AVE_OPERATOR) { + if (ch == '{' || ch == '(') { + levelCurrent++; + } else if (ch == '}' || ch == ')') { + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) { + visibleChars++; + } + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +extern const LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc); + diff --git a/src/lexilla/lexers/LexAVS.cxx b/src/lexilla/lexers/LexAVS.cxx new file mode 100644 index 000000000..60cb97289 --- /dev/null +++ b/src/lexilla/lexers/LexAVS.cxx @@ -0,0 +1,294 @@ +// Scintilla source code edit control +/** @file LexAVS.cxx + ** Lexer for AviSynth. + **/ +// Copyright 2012 by Bruno Barbieri +// Heavily based on LexPOV by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return isalpha(ch) || (ch != ' ' && ch != '\n' && ch != '(' && ch != '.' && ch != ','); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || ch == '.' || ch == '-' || ch == '+'); +} + +static void ColouriseAvsDoc( + Sci_PositionU startPos, + Sci_Position length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &filters = *keywordlists[1]; + WordList &plugins = *keywordlists[2]; + WordList &functions = *keywordlists[3]; + WordList &clipProperties = *keywordlists[4]; + WordList &userDefined = *keywordlists[5]; + + Sci_Position currentLine = styler.GetLine(startPos); + // Initialize the block comment nesting level, if we are inside such a comment. + int blockCommentLevel = 0; + if (initStyle == SCE_AVS_COMMENTBLOCK || initStyle == SCE_AVS_COMMENTBLOCKN) { + blockCommentLevel = styler.GetLineState(currentLine - 1); + } + + // Do not leak onto next line + if (initStyle == SCE_AVS_COMMENTLINE) { + initStyle = SCE_AVS_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + currentLine = styler.GetLine(sc.currentPos); + if (sc.state == SCE_AVS_COMMENTBLOCK || sc.state == SCE_AVS_COMMENTBLOCKN) { + // Inside a block comment, we set the line state + styler.SetLineState(currentLine, blockCommentLevel); + } else { + // Reset the line state + styler.SetLineState(currentLine, 0); + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_AVS_OPERATOR) { + sc.SetState(SCE_AVS_DEFAULT); + } else if (sc.state == SCE_AVS_NUMBER) { + // We stop the number definition on non-numerical non-dot non-sign char + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVS_KEYWORD); + } else if (filters.InList(s)) { + sc.ChangeState(SCE_AVS_FILTER); + } else if (plugins.InList(s)) { + sc.ChangeState(SCE_AVS_PLUGIN); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_AVS_FUNCTION); + } else if (clipProperties.InList(s)) { + sc.ChangeState(SCE_AVS_CLIPPROP); + } else if (userDefined.InList(s)) { + sc.ChangeState(SCE_AVS_USERDFN); + } + sc.SetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_COMMENTBLOCK) { + if (sc.Match('/', '*')) { + blockCommentLevel++; + sc.Forward(); + } else if (sc.Match('*', '/') && blockCommentLevel > 0) { + blockCommentLevel--; + sc.Forward(); + if (blockCommentLevel == 0) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + } else if (sc.state == SCE_AVS_COMMENTBLOCKN) { + if (sc.Match('[', '*')) { + blockCommentLevel++; + sc.Forward(); + } else if (sc.Match('*', ']') && blockCommentLevel > 0) { + blockCommentLevel--; + sc.Forward(); + if (blockCommentLevel == 0) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + } else if (sc.state == SCE_AVS_COMMENTLINE) { + if (sc.atLineEnd) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_TRIPLESTRING) { + if (sc.Match("\"\"\"")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_AVS_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_AVS_NUMBER); + } else if (IsADigit(sc.ch) || (sc.ch == ',' && IsADigit(sc.chNext))) { + sc.Forward(); + sc.SetState(SCE_AVS_NUMBER); + } else if (sc.Match('/', '*')) { + blockCommentLevel = 1; + sc.SetState(SCE_AVS_COMMENTBLOCK); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('[', '*')) { + blockCommentLevel = 1; + sc.SetState(SCE_AVS_COMMENTBLOCKN); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.ch == '#') { + sc.SetState(SCE_AVS_COMMENTLINE); + } else if (sc.ch == '\"') { + if (sc.Match("\"\"\"")) { + sc.SetState(SCE_AVS_TRIPLESTRING); + } else { + sc.SetState(SCE_AVS_STRING); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_AVS_OPERATOR); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_AVS_IDENTIFIER); + } + } + } + + // End of file: complete any pending changeState + if (sc.state == SCE_AVS_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVS_KEYWORD); + } else if (filters.InList(s)) { + sc.ChangeState(SCE_AVS_FILTER); + } else if (plugins.InList(s)) { + sc.ChangeState(SCE_AVS_PLUGIN); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_AVS_FUNCTION); + } else if (clipProperties.InList(s)) { + sc.ChangeState(SCE_AVS_CLIPPROP); + } else if (userDefined.InList(s)) { + sc.ChangeState(SCE_AVS_USERDFN); + } + sc.SetState(SCE_AVS_DEFAULT); + } + } + + sc.Complete(); +} + +static void FoldAvsDoc( + Sci_PositionU startPos, + Sci_Position length, + int initStyle, + WordList *[], + Accessor &styler) { + + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && style == SCE_AVS_COMMENTBLOCK) { + if (stylePrev != SCE_AVS_COMMENTBLOCK) { + levelCurrent++; + } else if ((styleNext != SCE_AVS_COMMENTBLOCK) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (foldComment && style == SCE_AVS_COMMENTBLOCKN) { + if (stylePrev != SCE_AVS_COMMENTBLOCKN) { + levelCurrent++; + } else if ((styleNext != SCE_AVS_COMMENTBLOCKN) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (style == SCE_AVS_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const avsWordLists[] = { + "Keywords", + "Filters", + "Plugins", + "Functions", + "Clip properties", + "User defined functions", + 0, +}; + +extern const LexerModule lmAVS(SCLEX_AVS, ColouriseAvsDoc, "avs", FoldAvsDoc, avsWordLists); diff --git a/src/lexilla/lexers/LexAbaqus.cxx b/src/lexilla/lexers/LexAbaqus.cxx new file mode 100644 index 000000000..db3a14a14 --- /dev/null +++ b/src/lexilla/lexers/LexAbaqus.cxx @@ -0,0 +1,606 @@ +// Scintilla source code edit control +/** @file LexAbaqus.cxx + ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz. + ** By Sergio Lucato. + ** Sort of completely rewritten by Gertjan Kloosterman + **/ +// The License.txt file describes the conditions under which this software may be distributed. + +// Code folding copyied and modified from LexBasic.cxx + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsAKeywordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' '))); +} + +static inline bool IsASetChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == '.') || (ch == '-'))); +} + +static void ColouriseABAQUSDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList*[] /* *keywordlists[] */, + Accessor &styler) { + enum localState { KW_LINE_KW, KW_LINE_COMMA, KW_LINE_PAR, KW_LINE_EQ, KW_LINE_VAL, \ + DAT_LINE_VAL, DAT_LINE_COMMA,\ + COMMENT_LINE,\ + ST_ERROR, LINE_END } state ; + + // Do not leak onto next line + state = LINE_END ; + initStyle = SCE_ABAQUS_DEFAULT; + StyleContext sc(startPos, length, initStyle, styler); + + // Things are actually quite simple + // we have commentlines + // keywordlines and datalines + // On a data line there will only be colouring of numbers + // a keyword line is constructed as + // *word,[ paramname[=paramvalue]]* + // if the line ends with a , the keyword line continues onto the new line + + for (; sc.More(); sc.Forward()) { + switch ( state ) { + case KW_LINE_KW : + if ( sc.atLineEnd ) { + // finished the line in keyword state, switch to LINE_END + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsAKeywordChar(sc.ch) ) { + // nothing changes + state = KW_LINE_KW ; + } else if ( sc.ch == ',' ) { + // Well well we say a comma, arguments *MUST* follow + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else { + // Flag an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + // Done with processing + break ; + case KW_LINE_COMMA : + // acomma on a keywordline was seen + if ( IsAKeywordChar(sc.ch)) { + sc.SetState(SCE_ABAQUS_ARGUMENT) ; + state = KW_LINE_PAR ; + } else if ( sc.atLineEnd || (sc.ch == ',') ) { + // we remain in keyword mode + state = KW_LINE_COMMA ; + } else if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_COMMA ; + } else { + // Anything else constitutes an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_PAR : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsAKeywordChar(sc.ch) || (sc.ch == '-') ) { + // remain in this state + state = KW_LINE_PAR ; + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else if ( sc.ch == '=' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_EQ ; + } else { + // Anything else constitutes an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_EQ : + if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + // remain in this state + state = KW_LINE_EQ ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-') || (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = KW_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = KW_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_VAL : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { + // nothing changes + state = KW_LINE_VAL ; + } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && + (sc.state == SCE_ABAQUS_NUMBER)) { + // remain in number mode + state = KW_LINE_VAL ; + } else if (sc.state == SCE_ABAQUS_STRING) { + // accept everything until a closing quote + if ( sc.ch == '\'' || sc.ch == '\"' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_VAL ; + } + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else { + // anything else is an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case DAT_LINE_VAL : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { + // nothing changes + state = DAT_LINE_VAL ; + } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && + (sc.state == SCE_ABAQUS_NUMBER)) { + // remain in number mode + state = DAT_LINE_VAL ; + } else if (sc.state == SCE_ABAQUS_STRING) { + // accept everything until a closing quote + if ( sc.ch == '\'' || sc.ch == '\"' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else { + // anything else is an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case DAT_LINE_COMMA : + // a comma on a data line was seen + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_COMMA ; + } else if (sc.ch == ',') { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = DAT_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = DAT_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case COMMENT_LINE : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } + break ; + case ST_ERROR : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } + break ; + case LINE_END : + if ( sc.atLineEnd || sc.ch == ' ' ) { + // nothing changes + state = LINE_END ; + } else if ( sc.ch == '*' ) { + if ( sc.chNext == '*' ) { + state = COMMENT_LINE ; + sc.SetState(SCE_ABAQUS_COMMENT) ; + } else { + state = KW_LINE_KW ; + sc.SetState(SCE_ABAQUS_STARCOMMAND) ; + } + } else { + // it must be a data line, things are as if we are in DAT_LINE_COMMA + if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = DAT_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = DAT_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + } + break ; + } + } + sc.Complete(); +} + +//------------------------------------------------------------------------------ +// This copyied and modified from LexBasic.cxx +//------------------------------------------------------------------------------ + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static Sci_Position LineEnd(Sci_Position line, Accessor &styler) +{ + const Sci_Position docLines = styler.GetLine(styler.Length() - 1); // Available last line + Sci_Position eol_pos ; + // if the line is the last line, the eol_pos is styler.Length() + // eol will contain a new line, or a virtual new line + if ( docLines == line ) + eol_pos = styler.Length() ; + else + eol_pos = styler.LineStart(line + 1) - 1; + return eol_pos ; +} + +static Sci_Position LineStart(Sci_Position line, Accessor &styler) +{ + return styler.LineStart(line) ; +} + +// LineType +// +// bits determines the line type +// 1 : data line +// 2 : only whitespace +// 3 : data line with only whitespace +// 4 : keyword line +// 5 : block open keyword line +// 6 : block close keyword line +// 7 : keyword line in error +// 8 : comment line +static int LineType(Sci_Position line, Accessor &styler) { + Sci_Position pos = LineStart(line, styler) ; + Sci_Position eol_pos = LineEnd(line, styler) ; + + int c ; + char ch = ' '; + + Sci_Position i = pos ; + while ( i < eol_pos ) { + c = styler.SafeGetCharAt(i); + ch = static_cast(LowerCase(c)); + // We can say something as soon as no whitespace + // was encountered + if ( !IsSpace(c) ) + break ; + i++ ; + } + + if ( i >= eol_pos ) { + // This is a whitespace line, currently + // classifies as data line + return 3 ; + } + + if ( ch != '*' ) { + // This is a data line + return 1 ; + } + + if ( i == eol_pos - 1 ) { + // Only a single *, error but make keyword line + return 4+3 ; + } + + // This means we can have a second character + // if that is also a * this means a comment + // otherwise it is a keyword. + c = styler.SafeGetCharAt(i+1); + ch = static_cast(LowerCase(c)); + if ( ch == '*' ) { + return 8 ; + } + + // At this point we know this is a keyword line + // the character at position i is a * + // it is not a comment line + char word[256] ; + int wlen = 0; + + word[wlen] = '*' ; + wlen++ ; + + i++ ; + while ( (i < eol_pos) && (wlen < 255) ) { + c = styler.SafeGetCharAt(i); + ch = static_cast(LowerCase(c)); + + if ( (!IsSpace(c)) && (!IsIdentifier(c)) ) + break ; + + if ( IsIdentifier(c) ) { + word[wlen] = ch ; + wlen++ ; + } + + i++ ; + } + + word[wlen] = 0 ; + + // Make a comparison + if ( !strcmp(word, "*step") || + !strcmp(word, "*part") || + !strcmp(word, "*instance") || + !strcmp(word, "*assembly")) { + return 4+1 ; + } + + if ( !strcmp(word, "*endstep") || + !strcmp(word, "*endpart") || + !strcmp(word, "*endinstance") || + !strcmp(word, "*endassembly")) { + return 4+2 ; + } + + return 4 ; +} + +static void SafeSetLevel(Sci_Position line, int level, Accessor &styler) +{ + if ( line < 0 ) + return ; + + int mask = ((~SC_FOLDLEVELHEADERFLAG) | (~SC_FOLDLEVELWHITEFLAG)); + + if ( (level & mask) < 0 ) + return ; + + if ( styler.LevelAt(line) != level ) + styler.SetLevel(line, level) ; +} + +static void FoldABAQUSDoc(Sci_PositionU startPos, Sci_Position length, int, +WordList *[], Accessor &styler) { + Sci_Position startLine = styler.GetLine(startPos) ; + Sci_Position endLine = styler.GetLine(startPos+length-1) ; + + // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // We want to deal with all the cases + // To know the correct indentlevel, we need to look back to the + // previous command line indentation level + // order of formatting keyline datalines commentlines + Sci_Position beginData = -1 ; + Sci_Position beginComment = -1 ; + Sci_Position prvKeyLine = startLine ; + Sci_Position prvKeyLineTp = 0 ; + + // Scan until we find the previous keyword line + // this will give us the level reference that we need + while ( prvKeyLine > 0 ) { + prvKeyLine-- ; + prvKeyLineTp = LineType(prvKeyLine, styler) ; + if ( prvKeyLineTp & 4 ) + break ; + } + + // Determine the base line level of all lines following + // the previous keyword + // new keyword lines are placed on this level + //if ( prvKeyLineTp & 4 ) { + int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ; + //} + + // uncomment line below if weird behaviour continues + prvKeyLine = -1 ; + + // Now start scanning over the lines. + for ( Sci_Position line = startLine; line <= endLine; line++ ) { + int lineType = LineType(line, styler) ; + + // Check for comment line + if ( lineType == 8 ) { + if ( beginComment < 0 ) { + beginComment = line ; + } + } + + // Check for data line + if ( (lineType == 1) || (lineType == 3) ) { + if ( beginData < 0 ) { + if ( beginComment >= 0 ) { + beginData = beginComment ; + } else { + beginData = line ; + } + } + beginComment = -1 ; + } + + // Check for keywordline. + // As soon as a keyword line is encountered, we can set the + // levels of everything from the previous keyword line to this one + if ( lineType & 4 ) { + // this is a keyword, we can now place the previous keyword + // all its data lines and the remainder + + // Write comments and data line + if ( beginComment < 0 ) { + beginComment = line ; + } + + if ( beginData < 0 ) { + beginData = beginComment ; + if ( prvKeyLineTp != 5 ) + SafeSetLevel(prvKeyLine, level, styler) ; + else + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } else { + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } + + int datLevel = level + 1 ; + if ( !(prvKeyLineTp & 4) ) { + datLevel = level ; + } + + for ( Sci_Position ll = beginData; ll < beginComment; ll++ ) + SafeSetLevel(ll, datLevel, styler) ; + + // The keyword we just found is going to be written at another level + // if we have a type 5 and type 6 + if ( prvKeyLineTp == 5 ) { + level += 1 ; + } + + if ( prvKeyLineTp == 6 ) { + level -= 1 ; + if ( level < 0 ) { + level = 0 ; + } + } + + for ( Sci_Position lll = beginComment; lll < line; lll++ ) + SafeSetLevel(lll, level, styler) ; + + // wrap and reset + beginComment = -1 ; + beginData = -1 ; + prvKeyLine = line ; + prvKeyLineTp = lineType ; + } + + } + + if ( beginComment < 0 ) { + beginComment = endLine + 1 ; + } else { + // We need to find out whether this comment block is followed by + // a data line or a keyword line + const Sci_Position docLines = styler.GetLine(styler.Length() - 1); + + for ( Sci_Position line = endLine + 1; line <= docLines; line++ ) { + Sci_Position lineType = LineType(line, styler) ; + + if ( lineType != 8 ) { + if ( !(lineType & 4) ) { + beginComment = endLine + 1 ; + } + break ; + } + } + } + + if ( beginData < 0 ) { + beginData = beginComment ; + if ( prvKeyLineTp != 5 ) + SafeSetLevel(prvKeyLine, level, styler) ; + else + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } else { + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } + + int datLevel = level + 1 ; + if ( !(prvKeyLineTp & 4) ) { + datLevel = level ; + } + + for ( Sci_Position ll = beginData; ll < beginComment; ll++ ) + SafeSetLevel(ll, datLevel, styler) ; + + if ( prvKeyLineTp == 5 ) { + level += 1 ; + } + + if ( prvKeyLineTp == 6 ) { + level -= 1 ; + } + for ( Sci_Position m = beginComment; m <= endLine; m++ ) + SafeSetLevel(m, level, styler) ; +} + +static const char * const abaqusWordListDesc[] = { + "processors", + "commands", + "slashommands", + "starcommands", + "arguments", + "functions", + 0 +}; + +extern const LexerModule lmAbaqus(SCLEX_ABAQUS, ColouriseABAQUSDoc, "abaqus", FoldABAQUSDoc, abaqusWordListDesc); diff --git a/src/lexilla/lexers/LexAda.cxx b/src/lexilla/lexers/LexAda.cxx new file mode 100644 index 000000000..4fbaaf1a2 --- /dev/null +++ b/src/lexilla/lexers/LexAda.cxx @@ -0,0 +1,514 @@ +// Scintilla source code edit control +/** @file LexAda.cxx + ** Lexer for Ada 95 + **/ +// Copyright 2002 by Sergey Koshcheyev +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +/* + * Interface + */ + +static void ColouriseDocument( + Sci_PositionU startPos, + Sci_Position length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static const char * const adaWordListDesc[] = { + "Keywords", + 0 +}; + +extern const LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc); + +/* + * Implementation + */ + +// Functions that have apostropheStartsAttribute as a parameter set it according to whether +// an apostrophe encountered after processing the current token will start an attribute or +// a character literal. +static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL); +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); + +static inline bool IsDelimiterCharacter(int ch); +static inline bool IsSeparatorOrDelimiterCharacter(int ch); +static bool IsValidIdentifier(const std::string& identifier); +static bool IsValidNumber(const std::string& number); +static inline bool IsWordStartCharacter(int ch); +static inline bool IsWordCharacter(int ch); + +static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + sc.SetState(SCE_ADA_CHARACTER); + + // Skip the apostrophe and one more character (so that '' is shown as non-terminated and ''' + // is handled correctly) + sc.Forward(); + sc.Forward(); + + ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL); +} + +static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) { + while (!sc.atLineEnd && !sc.Match(chEnd)) { + sc.Forward(); + } + + if (!sc.atLineEnd) { + sc.ForwardSetState(SCE_ADA_DEFAULT); + } else { + sc.ChangeState(stateEOL); + } +} + +static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { + // Apostrophe meaning is not changed, but the parameter is present for uniformity + + sc.SetState(SCE_ADA_COMMENTLINE); + + while (!sc.atLineEnd) { + sc.Forward(); + } +} + +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = sc.Match (')'); + sc.SetState(SCE_ADA_DELIMITER); + sc.ForwardSetState(SCE_ADA_DEFAULT); +} + +static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = false; + + sc.SetState(SCE_ADA_LABEL); + + // Skip "<<" + sc.Forward(); + sc.Forward(); + + std::string identifier; + + while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { + identifier += static_cast(tolower(sc.ch)); + sc.Forward(); + } + + // Skip ">>" + if (sc.Match('>', '>')) { + sc.Forward(); + sc.Forward(); + } else { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + // If the name is an invalid identifier or a keyword, then make it invalid label + if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + sc.SetState(SCE_ADA_DEFAULT); + +} + +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + std::string number; + sc.SetState(SCE_ADA_NUMBER); + + // Get all characters up to a delimiter or a separator, including points, but excluding + // double points (ranges). + while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) { + number += static_cast(sc.ch); + sc.Forward(); + } + + // Special case: exponent with sign + if ((sc.chPrev == 'e' || sc.chPrev == 'E') && + (sc.ch == '+' || sc.ch == '-')) { + number += static_cast(sc.ch); + sc.Forward (); + + while (!IsSeparatorOrDelimiterCharacter(sc.ch)) { + number += static_cast(sc.ch); + sc.Forward(); + } + } + + if (!IsValidNumber(number)) { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + sc.SetState(SCE_ADA_DEFAULT); +} + +static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + sc.SetState(SCE_ADA_STRING); + sc.Forward(); + + ColouriseContext(sc, '"', SCE_ADA_STRINGEOL); +} + +static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { + // Apostrophe meaning is not changed, but the parameter is present for uniformity + sc.SetState(SCE_ADA_DEFAULT); + sc.ForwardSetState(SCE_ADA_DEFAULT); +} + +static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + sc.SetState(SCE_ADA_IDENTIFIER); + + std::string word; + + while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { + word += static_cast(tolower(sc.ch)); + sc.Forward(); + } + + if (!IsValidIdentifier(word)) { + sc.ChangeState(SCE_ADA_ILLEGAL); + + } else if (keywords.InList(word.c_str())) { + sc.ChangeState(SCE_ADA_WORD); + + if (word != "all") { + apostropheStartsAttribute = false; + } + } + + sc.SetState(SCE_ADA_DEFAULT); +} + +// +// ColouriseDocument +// + +static void ColouriseDocument( + Sci_PositionU startPos, + Sci_Position length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + + StyleContext sc(startPos, length, initStyle, styler); + + Sci_Position lineCurrent = styler.GetLine(startPos); + bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0; + + while (sc.More()) { + if (sc.atLineEnd) { + // Go to the next line + sc.Forward(); + lineCurrent++; + + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, apostropheStartsAttribute); + + // Don't continue any styles on the next line + sc.SetState(SCE_ADA_DEFAULT); + } + + // Comments + if (sc.Match('-', '-')) { + ColouriseComment(sc, apostropheStartsAttribute); + + // Strings + } else if (sc.Match('"')) { + ColouriseString(sc, apostropheStartsAttribute); + + // Characters + } else if (sc.Match('\'') && !apostropheStartsAttribute) { + ColouriseCharacter(sc, apostropheStartsAttribute); + + // Labels + } else if (sc.Match('<', '<')) { + ColouriseLabel(sc, keywords, apostropheStartsAttribute); + + // Whitespace + } else if (IsASpace(sc.ch)) { + ColouriseWhiteSpace(sc, apostropheStartsAttribute); + + // Delimiters + } else if (IsDelimiterCharacter(sc.ch)) { + ColouriseDelimiter(sc, apostropheStartsAttribute); + + // Numbers + } else if (IsADigit(sc.ch) || sc.ch == '#') { + ColouriseNumber(sc, apostropheStartsAttribute); + + // Keywords or identifiers + } else { + ColouriseWord(sc, keywords, apostropheStartsAttribute); + } + } + + sc.Complete(); +} + +static inline bool IsDelimiterCharacter(int ch) { + switch (ch) { + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case '-': + case '.': + case '/': + case ':': + case ';': + case '<': + case '=': + case '>': + case '|': + return true; + default: + return false; + } +} + +static inline bool IsSeparatorOrDelimiterCharacter(int ch) { + return IsASpace(ch) || IsDelimiterCharacter(ch); +} + +static bool IsValidIdentifier(const std::string& identifier) { + // First character can't be '_', so initialize the flag to true + bool lastWasUnderscore = true; + + size_t length = identifier.length(); + + // Zero-length identifiers are not valid (these can occur inside labels) + if (length == 0) { + return false; + } + + // Check for valid character at the start + if (!IsWordStartCharacter(identifier[0])) { + return false; + } + + // Check for only valid characters and no double underscores + for (size_t i = 0; i < length; i++) { + if (!IsWordCharacter(identifier[i]) || + (identifier[i] == '_' && lastWasUnderscore)) { + return false; + } + lastWasUnderscore = identifier[i] == '_'; + } + + // Check for underscore at the end + if (lastWasUnderscore == true) { + return false; + } + + // All checks passed + return true; +} + +static bool IsValidNumber(const std::string& number) { + size_t hashPos = number.find("#"); + bool seenDot = false; + + size_t i = 0; + size_t length = number.length(); + + if (length == 0) + return false; // Just in case + + // Decimal number + if (hashPos == std::string::npos) { + bool canBeSpecial = false; + + for (; i < length; i++) { + if (number[i] == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + } else if (number[i] == '.') { + if (!canBeSpecial || seenDot) { + return false; + } + canBeSpecial = false; + seenDot = true; + } else if (IsADigit(number[i])) { + canBeSpecial = true; + } else { + break; + } + } + + if (!canBeSpecial) + return false; + } else { + // Based number + bool canBeSpecial = false; + int base = 0; + + // Parse base + for (; i < length; i++) { + int ch = number[i]; + if (ch == '_') { + if (!canBeSpecial) + return false; + canBeSpecial = false; + } else if (IsADigit(ch)) { + base = base * 10 + (ch - '0'); + if (base > 16) + return false; + canBeSpecial = true; + } else if (ch == '#' && canBeSpecial) { + break; + } else { + return false; + } + } + + if (base < 2) + return false; + if (i == length) + return false; + + i++; // Skip over '#' + + // Parse number + canBeSpecial = false; + + for (; i < length; i++) { + int ch = tolower(number[i]); + + if (ch == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + + } else if (ch == '.') { + if (!canBeSpecial || seenDot) { + return false; + } + canBeSpecial = false; + seenDot = true; + + } else if (IsADigit(ch)) { + if (ch - '0' >= base) { + return false; + } + canBeSpecial = true; + + } else if (ch >= 'a' && ch <= 'f') { + if (ch - 'a' + 10 >= base) { + return false; + } + canBeSpecial = true; + + } else if (ch == '#' && canBeSpecial) { + break; + + } else { + return false; + } + } + + if (i == length) { + return false; + } + + i++; + } + + // Exponent (optional) + if (i < length) { + if (number[i] != 'e' && number[i] != 'E') + return false; + + i++; // Move past 'E' + + if (i == length) { + return false; + } + + if (number[i] == '+') + i++; + else if (number[i] == '-') { + if (seenDot) { + i++; + } else { + return false; // Integer literals should not have negative exponents + } + } + + if (i == length) { + return false; + } + + bool canBeSpecial = false; + + for (; i < length; i++) { + if (number[i] == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + } else if (IsADigit(number[i])) { + canBeSpecial = true; + } else { + return false; + } + } + + if (!canBeSpecial) + return false; + } + + // if i == length, number was parsed successfully. + return i == length; +} + +static inline bool IsWordCharacter(int ch) { + return IsWordStartCharacter(ch) || IsADigit(ch); +} + +static inline bool IsWordStartCharacter(int ch) { + return (IsASCII(ch) && isalpha(ch)) || ch == '_'; +} diff --git a/src/lexilla/lexers/LexAsciidoc.cxx b/src/lexilla/lexers/LexAsciidoc.cxx new file mode 100644 index 000000000..dc82e30a7 --- /dev/null +++ b/src/lexilla/lexers/LexAsciidoc.cxx @@ -0,0 +1,393 @@ +/****************************************************************** + * LexAsciidoc.cxx + * + * A simple Asciidoc lexer for scintilla. + * + * Based on the LexMarkdown.cxx by Jon Strait - jstrait@moonloop.net + * + * The License.txt file describes the conditions under which this + * software may be distributed. + * + *****************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +namespace { + +typedef struct { + bool start; + int len1; + int len2; + const char *name; +} MacroItem; + +static const MacroItem MacroList[] = { + // Directives + {true, 5, 2, "ifdef::"}, + {true, 6, 2, "ifeval::"}, + {true, 6, 2, "ifndef::"}, + {true, 5, 2, "endif::"}, + // Macros + {true, 5, 2, "audio::"}, + {true, 7, 2, "include::"}, + {true, 5, 2, "image::"}, + {true, 5, 2, "video::"}, + {false, 8, 1, "asciimath:"}, + {false, 3, 1, "btn:"}, + {false, 5, 1, "image:"}, + {false, 3, 1, "kbd:"}, + {false, 9, 1, "latexmath:"}, + {false, 4, 1, "link:"}, + {false, 6, 1, "mailto:"}, + {false, 4, 1, "menu:"}, + {false, 4, 1, "pass:"}, + {false, 4, 1, "stem:"}, + {false, 4, 1, "xref:"}, + // Admonitions + {true, 7, 1, "CAUTION:"}, + {true, 9, 1, "IMPORTANT:"}, + {true, 4, 1, "NOTE:"}, + {true, 3, 1, "TIP:"}, + {true, 7, 1, "WARNING:"}, + {false, 0, 0, NULL} +}; + +constexpr bool IsNewline(const int ch) { + // sc.GetRelative(i) returns '\0' if out of range + return (ch == '\n' || ch == '\r' || ch == '\0'); +} + +} + +static bool AtTermStart(StyleContext &sc) { + return sc.currentPos == 0 || sc.chPrev == 0 || isspacechar(sc.chPrev); +} + +static void ColorizeAsciidocDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList **, Accessor &styler) { + bool freezeCursor = false; + + StyleContext sc(startPos, static_cast(length), initStyle, styler); + + while (sc.More()) { + // Skip past escaped characters + if (sc.ch == '\\') { + sc.Forward(); + continue; + } + + // Skip newline. + if (IsNewline(sc.ch)) { + // Newline doesn't end blocks + if (sc.state != SCE_ASCIIDOC_CODEBK && \ + sc.state != SCE_ASCIIDOC_PASSBK && \ + sc.state != SCE_ASCIIDOC_COMMENTBK && \ + sc.state != SCE_ASCIIDOC_LITERALBK) { + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + sc.Forward(); + continue; + } + + // Conditional state-based actions + switch (sc.state) { + + // Strong + case SCE_ASCIIDOC_STRONG1: + if (sc.ch == '*' && sc.chPrev != ' ') { + sc.Forward(); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + freezeCursor = true; + } + break; + case SCE_ASCIIDOC_STRONG2: + if (sc.Match("**") && sc.chPrev != ' ') { + sc.Forward(2); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + freezeCursor = true; + } + break; + + // Emphasis + case SCE_ASCIIDOC_EM1: + if (sc.ch == '_' && sc.chPrev != ' ') { + sc.Forward(); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + freezeCursor = true; + } + break; + case SCE_ASCIIDOC_EM2: + if (sc.Match("__") && sc.chPrev != ' ') { + sc.Forward(2); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + freezeCursor = true; + } + break; + + // Link + case SCE_ASCIIDOC_LINK: + if (sc.ch == ']' && sc.chPrev != '\\') { + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + break; + + // Code block + case SCE_ASCIIDOC_CODEBK: + if (sc.atLineStart && sc.Match("----") && IsNewline(sc.GetRelative(4))) { + sc.Forward(4); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + break; + + // Passthrough block + case SCE_ASCIIDOC_PASSBK: + if (sc.atLineStart && sc.Match("++++") && IsNewline(sc.GetRelative(4))) { + sc.Forward(4); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + break; + + // Comment block + case SCE_ASCIIDOC_COMMENTBK: + if (sc.atLineStart && sc.Match("////") && IsNewline(sc.GetRelative(4))) { + sc.Forward(4); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + break; + + // Literal + case SCE_ASCIIDOC_LITERAL: + if (sc.ch == '+' && sc.chPrev != '\\') { + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + break; + + // Literal block + case SCE_ASCIIDOC_LITERALBK: + if (sc.atLineStart && sc.Match("....") && IsNewline(sc.GetRelative(4))) { + sc.Forward(4); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + break; + + // Attribute + case SCE_ASCIIDOC_ATTRIB: + if (sc.ch == ':' && sc.chPrev != ' ' && sc.chNext == ' ') { + sc.Forward(); + sc.SetState(SCE_ASCIIDOC_ATTRIBVAL); + } + break; + + // Macro + case SCE_ASCIIDOC_MACRO: + if (sc.ch == ']' && sc.chPrev != '\\') { + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + break; + + // Default + case SCE_ASCIIDOC_DEFAULT: + // Headers + if (sc.atLineStart && sc.Match("====== ")) { + sc.SetState(SCE_ASCIIDOC_HEADER6); + sc.Forward(6); + } + else if (sc.atLineStart && sc.Match("===== ")) { + sc.SetState(SCE_ASCIIDOC_HEADER5); + sc.Forward(5); + } + else if (sc.atLineStart && sc.Match("==== ")) { + sc.SetState(SCE_ASCIIDOC_HEADER4); + sc.Forward(4); + } + else if (sc.atLineStart && sc.Match("=== ")) { + sc.SetState(SCE_ASCIIDOC_HEADER3); + sc.Forward(3); + } + else if (sc.atLineStart && sc.Match("== ")) { + sc.SetState(SCE_ASCIIDOC_HEADER2); + sc.Forward(2); + } + else if (sc.atLineStart && sc.Match("= ")) { + sc.SetState(SCE_ASCIIDOC_HEADER1); + sc.Forward(1); + } + // Unordered list item + else if (sc.atLineStart && sc.Match("****** ")) { + sc.SetState(SCE_ASCIIDOC_ULIST_ITEM); + sc.Forward(6); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match("***** ")) { + sc.SetState(SCE_ASCIIDOC_ULIST_ITEM); + sc.Forward(5); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match("**** ")) { + sc.SetState(SCE_ASCIIDOC_ULIST_ITEM); + sc.Forward(4); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match("*** ")) { + sc.SetState(SCE_ASCIIDOC_ULIST_ITEM); + sc.Forward(3); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match("** ")) { + sc.SetState(SCE_ASCIIDOC_ULIST_ITEM); + sc.Forward(2); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match("* ")) { + sc.SetState(SCE_ASCIIDOC_ULIST_ITEM); + sc.Forward(1); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + // Ordered list item + else if (sc.atLineStart && sc.Match("...... ")) { + sc.SetState(SCE_ASCIIDOC_OLIST_ITEM); + sc.Forward(6); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match("..... ")) { + sc.SetState(SCE_ASCIIDOC_OLIST_ITEM); + sc.Forward(5); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match(".... ")) { + sc.SetState(SCE_ASCIIDOC_OLIST_ITEM); + sc.Forward(4); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match("... ")) { + sc.SetState(SCE_ASCIIDOC_OLIST_ITEM); + sc.Forward(3); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match(".. ")) { + sc.SetState(SCE_ASCIIDOC_OLIST_ITEM); + sc.Forward(2); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + else if (sc.atLineStart && sc.Match(". ")) { + sc.SetState(SCE_ASCIIDOC_OLIST_ITEM); + sc.Forward(1); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + } + // Blockquote + else if (sc.atLineStart && sc.Match("> ")) { + sc.SetState(SCE_ASCIIDOC_BLOCKQUOTE); + sc.Forward(); + } + // Link + else if (!sc.atLineStart && sc.ch == '[' && sc.chPrev != '\\' && sc.chNext != ' ') { + sc.Forward(); + sc.SetState(SCE_ASCIIDOC_LINK); + freezeCursor = true; + } + // Code block + else if (sc.atLineStart && sc.Match("----") && IsNewline(sc.GetRelative(4))) { + sc.SetState(SCE_ASCIIDOC_CODEBK); + sc.Forward(4); + } + // Passthrough block + else if (sc.atLineStart && sc.Match("++++") && IsNewline(sc.GetRelative(4))) { + sc.SetState(SCE_ASCIIDOC_PASSBK); + sc.Forward(4); + } + // Comment block + else if (sc.atLineStart && sc.Match("////") && IsNewline(sc.GetRelative(4))) { + sc.SetState(SCE_ASCIIDOC_COMMENTBK); + sc.Forward(4); + } + // Comment + else if (sc.atLineStart && sc.Match("//")) { + sc.SetState(SCE_ASCIIDOC_COMMENT); + sc.Forward(); + } + // Literal + else if (sc.ch == '+' && sc.chPrev != '\\' && sc.chNext != ' ' && AtTermStart(sc)) { + sc.Forward(); + sc.SetState(SCE_ASCIIDOC_LITERAL); + freezeCursor = true; + } + // Literal block + else if (sc.atLineStart && sc.Match("....") && IsNewline(sc.GetRelative(4))) { + sc.SetState(SCE_ASCIIDOC_LITERALBK); + sc.Forward(4); + } + // Attribute + else if (sc.atLineStart && sc.ch == ':' && sc.chNext != ' ') { + sc.SetState(SCE_ASCIIDOC_ATTRIB); + } + // Strong + else if (sc.Match("**") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_ASCIIDOC_STRONG2); + sc.Forward(); + } + else if (sc.ch == '*' && sc.chNext != ' ' && AtTermStart(sc)) { + sc.SetState(SCE_ASCIIDOC_STRONG1); + } + // Emphasis + else if (sc.Match("__") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_ASCIIDOC_EM2); + sc.Forward(); + } + else if (sc.ch == '_' && sc.chNext != ' ' && AtTermStart(sc)) { + sc.SetState(SCE_ASCIIDOC_EM1); + } + // Macro + else if (sc.atLineStart && sc.ch == '[' && sc.chNext != ' ') { + sc.Forward(); + sc.SetState(SCE_ASCIIDOC_MACRO); + freezeCursor = true; + } + else { + int i = 0; + bool found = false; + while (!found && MacroList[i].name != NULL) { + if (MacroList[i].start) + found = sc.atLineStart && sc.Match(MacroList[i].name); + else + found = sc.Match(MacroList[i].name); + if (found) { + sc.SetState(SCE_ASCIIDOC_MACRO); + sc.Forward(MacroList[i].len1); + sc.SetState(SCE_ASCIIDOC_DEFAULT); + if (MacroList[i].len2 > 1) + sc.Forward(MacroList[i].len2 - 1); + } + i++; + } + } + break; + } + // Advance if not holding back the cursor for this iteration. + if (!freezeCursor) + sc.Forward(); + freezeCursor = false; + } + sc.Complete(); +} + +extern const LexerModule lmAsciidoc(SCLEX_ASCIIDOC, ColorizeAsciidocDoc, "asciidoc"); diff --git a/src/lexilla/lexers/LexAsm.cxx b/src/lexilla/lexers/LexAsm.cxx new file mode 100644 index 000000000..40bf7b46f --- /dev/null +++ b/src/lexilla/lexers/LexAsm.cxx @@ -0,0 +1,479 @@ +// Scintilla source code edit control +/** @file LexAsm.cxx + ** Lexer for Assembler, just for the MASM syntax + ** Written by The Black Horus + ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 + ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + +bool IsAWordChar(const int ch) noexcept { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?'); +} + +bool IsAWordStart(const int ch) noexcept { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || + ch == '%' || ch == '@' || ch == '$' || ch == '?'); +} + +bool IsAsmOperator(const int ch) noexcept { + if ((ch < 0x80) && (isalnum(ch))) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '%' || ch == ':') + return true; + return false; +} + +constexpr bool IsStreamCommentStyle(int style) noexcept { + return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerAsm +struct OptionsAsm { + std::string delimiter; + bool fold; + bool foldSyntaxBased; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + std::string commentChar; + OptionsAsm() { + delimiter = ""; + fold = false; + foldSyntaxBased = true; + foldCommentMultiline = false; + foldCommentExplicit = false; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + commentChar = ""; + } +}; + +const char *const asmWordListDesc[] = { + "CPU instructions", + "FPU instructions", + "Registers", + "Directives", + "Directive operands", + "Extended instructions", + "Directives4Foldstart", + "Directives4Foldend", + nullptr +}; + +struct OptionSetAsm : public OptionSet { + OptionSetAsm() { + DefineProperty("lexer.asm.comment.delimiter", &OptionsAsm::delimiter, + "Character used for COMMENT directive's delimiter, replacing the standard \"~\"."); + + DefineProperty("fold", &OptionsAsm::fold); + + DefineProperty("fold.asm.syntax.based", &OptionsAsm::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.asm.comment.multiline", &OptionsAsm::foldCommentMultiline, + "Set this property to 1 to enable folding multi-line comments."); + + DefineProperty("fold.asm.comment.explicit", &OptionsAsm::foldCommentExplicit, + "This option enables folding explicit fold points when using the Asm lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} " + "at the end of a section that should fold."); + + DefineProperty("fold.asm.explicit.start", &OptionsAsm::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard ;{."); + + DefineProperty("fold.asm.explicit.end", &OptionsAsm::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard ;}."); + + DefineProperty("fold.asm.explicit.anywhere", &OptionsAsm::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsAsm::foldCompact); + + DefineProperty("lexer.as.comment.character", &OptionsAsm::commentChar, + "Overrides the default comment character (which is ';' for asm and '#' for as)."); + + DefineWordListSets(asmWordListDesc); + } +}; + +class LexerAsm : public DefaultLexer { + WordList cpuInstruction; + WordList mathInstruction; + WordList registers; + WordList directive; + WordList directiveOperand; + WordList extInstruction; + WordList directives4foldstart; + WordList directives4foldend; + OptionsAsm options; + OptionSetAsm osAsm; + int commentChar; +public: + LexerAsm(const char *languageName_, int language_, int commentChar_) : DefaultLexer(languageName_, language_) { + commentChar = commentChar_; + } + virtual ~LexerAsm() { + } + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char * SCI_METHOD PropertyNames() override { + return osAsm.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osAsm.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osAsm.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char *key) override { + return osAsm.PropertyGet(key); + } + const char * SCI_METHOD DescribeWordListSets() override { + return osAsm.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return nullptr; + } + + static ILexer5 *LexerFactoryAsm() { + return new LexerAsm("asm", SCLEX_ASM, ';'); + } + + static ILexer5 *LexerFactoryAs() { + return new LexerAsm("as", SCLEX_AS, '#'); + } +}; + +Sci_Position SCI_METHOD LexerAsm::PropertySet(const char *key, const char *val) { + if (osAsm.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + switch (n) { + case 0: + wordListN = &cpuInstruction; + break; + case 1: + wordListN = &mathInstruction; + break; + case 2: + wordListN = ®isters; + break; + case 3: + wordListN = &directive; + break; + case 4: + wordListN = &directiveOperand; + break; + case 5: + wordListN = &extInstruction; + break; + case 6: + wordListN = &directives4foldstart; + break; + case 7: + wordListN = &directives4foldend; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + if (wordListN->Set(wl, true)) { + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + const char commentCharacter = options.commentChar.empty() ? + commentChar : options.commentChar.front(); + + // Do not leak onto next line + if (initStyle == SCE_ASM_STRINGEOL) + initStyle = SCE_ASM_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + + if (sc.atLineStart) { + switch (sc.state) { + case SCE_ASM_STRING: + case SCE_ASM_CHARACTER: + // Prevent SCE_ASM_STRINGEOL from leaking back to previous line + sc.SetState(sc.state); + break; + case SCE_ASM_COMMENT: + sc.SetState(SCE_ASM_DEFAULT); + break; + default: + break; + } + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_ASM_OPERATOR) { + if (!IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_IDENTIFIER) { + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + bool IsDirective = false; + + if (cpuInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_CPUINSTRUCTION); + } else if (mathInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_MATHINSTRUCTION); + } else if (registers.InList(s)) { + sc.ChangeState(SCE_ASM_REGISTER); + } else if (directive.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVE); + IsDirective = true; + } else if (directiveOperand.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); + } else if (extInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_EXTINSTRUCTION); + } + sc.SetState(SCE_ASM_DEFAULT); + if (IsDirective && !strcmp(s, "comment")) { + const char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + if (sc.ch == delimiter) { + sc.SetState(SCE_ASM_COMMENTDIRECTIVE); + } + } + } + } else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) { + const char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + if (sc.ch == delimiter) { + while (!sc.MatchLineEnd()) { + sc.Forward(); + } + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_CHARACTER) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ASM_DEFAULT) { + if (sc.ch == commentCharacter) { + sc.SetState(SCE_ASM_COMMENT); + } else if (IsASCII(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && IsASCII(sc.chNext) && isdigit(sc.chNext)))) { + sc.SetState(SCE_ASM_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_ASM_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ASM_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ASM_CHARACTER); + } else if (IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_OPERATOR); + } + } + + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "else". + +void SCI_METHOD LexerAsm::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + const Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + char word[100]{}; + int wordlen = 0; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (Sci_PositionU i = startPos; i < endPos; i++) { + const char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + const int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if (ch == ';') { + if (chNext == '{') { + levelNext++; + } else if (chNext == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) { + word[wordlen++] = MakeLowerCase(ch); + if (wordlen == 100) { // prevent overflow + word[0] = '\0'; + wordlen = 1; + } + if (styleNext != SCE_ASM_DIRECTIVE) { // reading directive ready + word[wordlen] = '\0'; + wordlen = 0; + if (directives4foldstart.InList(word)) { + levelNext++; + } else if (directives4foldend.InList(word)){ + levelNext--; + } + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + const int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + if (atEOL && (i == static_cast(styler.Length() - 1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +} + +extern const LexerModule lmAsm(SCLEX_ASM, LexerAsm::LexerFactoryAsm, "asm", asmWordListDesc); +extern const LexerModule lmAs(SCLEX_AS, LexerAsm::LexerFactoryAs, "as", asmWordListDesc); + diff --git a/src/lexilla/lexers/LexAsn1.cxx b/src/lexilla/lexers/LexAsn1.cxx new file mode 100644 index 000000000..645644858 --- /dev/null +++ b/src/lexilla/lexers/LexAsn1.cxx @@ -0,0 +1,189 @@ +// Scintilla source code edit control +/** @file LexAsn1.cxx + ** Lexer for ASN.1 + **/ +// Copyright 2004 by Herr Pfarrer rpfarrer yahoo de +// Last Updated: 20/07/2004 +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +// Some char test functions +static bool isAsn1Number(int ch) +{ + return (ch >= '0' && ch <= '9'); +} + +static bool isAsn1Letter(int ch) +{ + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isAsn1Char(int ch) +{ + return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch); +} + +// +// Function determining the color of a given code portion +// Based on a "state" +// +static void ColouriseAsn1Doc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordLists[], Accessor &styler) +{ + // The keywords + WordList &Keywords = *keywordLists[0]; + WordList &Attributes = *keywordLists[1]; + WordList &Descriptors = *keywordLists[2]; + WordList &Types = *keywordLists[3]; + + // Parse the whole buffer character by character using StyleContext + StyleContext sc(startPos, length, initStyle, styler); + for (; sc.More(); sc.Forward()) + { + // The state engine + switch (sc.state) + { + case SCE_ASN1_DEFAULT: // Plain characters +asn1_default: + if (sc.ch == '-' && sc.chNext == '-') + // A comment begins here + sc.SetState(SCE_ASN1_COMMENT); + else if (sc.ch == '"') + // A string begins here + sc.SetState(SCE_ASN1_STRING); + else if (isAsn1Number (sc.ch)) + // A number starts here (identifier should start with a letter in ASN.1) + sc.SetState(SCE_ASN1_SCALAR); + else if (isAsn1Char (sc.ch)) + // An identifier starts here (identifier always start with a letter) + sc.SetState(SCE_ASN1_IDENTIFIER); + else if (sc.ch == ':') + // A ::= operator starts here + sc.SetState(SCE_ASN1_OPERATOR); + break; + case SCE_ASN1_COMMENT: // A comment + if (sc.ch == '\r' || sc.ch == '\n') + // A comment ends here + sc.SetState(SCE_ASN1_DEFAULT); + break; + case SCE_ASN1_IDENTIFIER: // An identifier (keyword, attribute, descriptor or type) + if (!isAsn1Char (sc.ch)) + { + // The end of identifier is here: we can look for it in lists by now and change its state + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (Keywords.InList(s)) + // It's a keyword, change its state + sc.ChangeState(SCE_ASN1_KEYWORD); + else if (Attributes.InList(s)) + // It's an attribute, change its state + sc.ChangeState(SCE_ASN1_ATTRIBUTE); + else if (Descriptors.InList(s)) + // It's a descriptor, change its state + sc.ChangeState(SCE_ASN1_DESCRIPTOR); + else if (Types.InList(s)) + // It's a type, change its state + sc.ChangeState(SCE_ASN1_TYPE); + + // Set to default now + sc.SetState(SCE_ASN1_DEFAULT); + } + break; + case SCE_ASN1_STRING: // A string delimited by "" + if (sc.ch == '"') + { + // A string ends here + sc.ForwardSetState(SCE_ASN1_DEFAULT); + + // To correctly manage a char sticking to the string quote + goto asn1_default; + } + break; + case SCE_ASN1_SCALAR: // A plain number + if (!isAsn1Number (sc.ch)) + // A number ends here + sc.SetState(SCE_ASN1_DEFAULT); + break; + case SCE_ASN1_OPERATOR: // The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap) + if (sc.ch == '{') + { + // An OID definition starts here: enter the sub loop + for (; sc.More(); sc.Forward()) + { + if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev))) + // The OID number is highlighted + sc.SetState(SCE_ASN1_OID); + else if (isAsn1Char (sc.ch)) + // The OID parent identifier is plain + sc.SetState(SCE_ASN1_IDENTIFIER); + else + sc.SetState(SCE_ASN1_DEFAULT); + + if (sc.ch == '}') + // Here ends the OID and the operator sub loop: go back to main loop + break; + } + } + else if (isAsn1Number (sc.ch)) + { + // A trap number definition starts here: enter the sub loop + for (; sc.More(); sc.Forward()) + { + if (isAsn1Number (sc.ch)) + // The trap number is highlighted + sc.SetState(SCE_ASN1_OID); + else + { + // The number ends here: go back to main loop + sc.SetState(SCE_ASN1_DEFAULT); + break; + } + } + } + else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ') + // The operator doesn't imply an OID definition nor a trap, back to main loop + goto asn1_default; // To be sure to handle actually the state change + break; + } + } + sc.Complete(); +} + +static void FoldAsn1Doc(Sci_PositionU, Sci_Position, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if( styler.GetPropertyInt("fold") == 0 ) + return; + + // No folding implemented: doesn't make sense for ASN.1 +} + +static const char * const asn1WordLists[] = { + "Keywords", + "Attributes", + "Descriptors", + "Types", + 0, }; + + +extern const LexerModule lmAsn1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists); diff --git a/src/lexilla/lexers/LexBaan.cxx b/src/lexilla/lexers/LexBaan.cxx new file mode 100644 index 000000000..5b8a385e5 --- /dev/null +++ b/src/lexilla/lexers/LexBaan.cxx @@ -0,0 +1,995 @@ +// Scintilla source code edit control +/** @file LexBaan.cxx +** Lexer for Baan. +** Based heavily on LexCPP.cxx +**/ +// Copyright 2001- by Vamsi Potluru & Praveen Ambekar +// Maintainer Email: oirfeodent@yahoo.co.in +// The License.txt file describes the conditions under which this software may be distributed. + +// C standard library +#include +#include + +// C++ wrappers of C standard library +#include + +// C++ standard library +#include +#include +#include +#include + +// Scintilla headers + +// Non-platform-specific headers + +// include +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +// lexlib +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { +// Use an unnamed namespace to protect the functions and classes from name conflicts + +// Options used for LexerBaan +struct OptionsBaan { + bool fold; + bool foldComment; + bool foldPreprocessor; + bool foldCompact; + bool baanFoldSyntaxBased; + bool baanFoldKeywordsBased; + bool baanFoldSections; + bool baanFoldInnerLevel; + bool baanStylingWithinPreprocessor; + OptionsBaan() { + fold = false; + foldComment = false; + foldPreprocessor = false; + foldCompact = false; + baanFoldSyntaxBased = false; + baanFoldKeywordsBased = false; + baanFoldSections = false; + baanFoldInnerLevel = false; + baanStylingWithinPreprocessor = false; + } +}; + +const char *const baanWordLists[] = { + "Baan & BaanSQL Reserved Keywords ", + "Baan Standard functions", + "Baan Functions Abridged", + "Baan Main Sections ", + "Baan Sub Sections", + "PreDefined Variables", + "PreDefined Attributes", + "Enumerates", + 0, +}; + +struct OptionSetBaan : public OptionSet { + OptionSetBaan() { + DefineProperty("fold", &OptionsBaan::fold); + + DefineProperty("fold.comment", &OptionsBaan::foldComment); + + DefineProperty("fold.preprocessor", &OptionsBaan::foldPreprocessor); + + DefineProperty("fold.compact", &OptionsBaan::foldCompact); + + DefineProperty("fold.baan.syntax.based", &OptionsBaan::baanFoldSyntaxBased, + "Set this property to 0 to disable syntax based folding, which is folding based on '{' & '('."); + + DefineProperty("fold.baan.keywords.based", &OptionsBaan::baanFoldKeywordsBased, + "Set this property to 0 to disable keywords based folding, which is folding based on " + " for, if, on (case), repeat, select, while and fold ends based on endfor, endif, endcase, until, endselect, endwhile respectively." + "Also folds declarations which are grouped together."); + + DefineProperty("fold.baan.sections", &OptionsBaan::baanFoldSections, + "Set this property to 0 to disable folding of Main Sections as well as Sub Sections."); + + DefineProperty("fold.baan.inner.level", &OptionsBaan::baanFoldInnerLevel, + "Set this property to 1 to enable folding of inner levels of select statements." + "Disabled by default. case and if statements are also eligible" ); + + DefineProperty("lexer.baan.styling.within.preprocessor", &OptionsBaan::baanStylingWithinPreprocessor, + "For Baan code, determines whether all preprocessor code is styled in the " + "preprocessor style (0, the default) or only from the initial # to the end " + "of the command word(1)."); + + DefineWordListSets(baanWordLists); + } +}; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$'); +} + +static inline bool IsAnOperator(int ch) { + if (IsAlphaNumeric(ch)) + return false; + if (ch == '#' || ch == '^' || ch == '&' || ch == '*' || + ch == '(' || ch == ')' || ch == '-' || ch == '+' || + ch == '=' || ch == '|' || ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ':' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || ch == '/' || + ch == '?' || ch == '!' || ch == '"' || ch == '~' || + ch == '\\') + return true; + return false; +} + +static inline int IsAnyOtherIdentifier(char *s, Sci_Position sLength) { + + /* IsAnyOtherIdentifier uses standard templates used in baan. + The matching template is shown as comments just above the return condition. + ^ - refers to any character [a-z]. + # - refers to any number [0-9]. + Other characters shown are compared as is. + Tried implementing with Regex... it was too complicated for me. + Any other implementation suggestion welcome. + */ + switch (sLength) { + case 8: + if (isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { + //^^^^^### + return(SCE_BAAN_TABLEDEF); + } + break; + case 9: + if (s[0] == 't' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8])) { + //t^^^^^### + return(SCE_BAAN_TABLEDEF); + } + else if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { + //^^^^^###. + return(SCE_BAAN_TABLESQL); + } + break; + case 13: + if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { + //^^^^^###.**** + return(SCE_BAAN_TABLESQL); + } + else if (s[0] == 'r' && s[1] == 'c' && s[2] == 'd' && s[3] == '.' && s[4] == 't' && isalpha(s[5]) && isalpha(s[6]) && isalpha(s[7]) && isalpha(s[8]) && isalpha(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) { + //rcd.t^^^^^### + return(SCE_BAAN_TABLEDEF); + } + break; + case 14: + case 15: + if (s[8] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { + if (s[13] != ':') { + //^^^^^###.****** + return(SCE_BAAN_TABLESQL); + } + } + break; + case 16: + case 17: + if (s[8] == '.' && s[9] == '_' && s[10] == 'i' && s[11] == 'n' && s[12] == 'd' && s[13] == 'e' && s[14] == 'x' && IsADigit(s[15]) && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { + //^^^^^###._index## + return(SCE_BAAN_TABLEDEF); + } + else if (s[8] == '.' && s[9] == '_' && s[10] == 'c' && s[11] == 'o' && s[12] == 'm' && s[13] == 'p' && s[14] == 'n' && s[15] == 'r' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[5]) && IsADigit(s[6]) && IsADigit(s[7])) { + //^^^^^###._compnr + return(SCE_BAAN_TABLEDEF); + } + break; + default: + break; + } + if (sLength > 14 && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && s[13] == '.' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && IsADigit(s[9]) && IsADigit(s[10]) && IsADigit(s[11]) && IsADigit(s[12])) { + //^^^^^.dll####. + return(SCE_BAAN_FUNCTION); + } + else if (sLength > 15 && s[2] == 'i' && s[3] == 'n' && s[4] == 't' && s[5] == '.' && s[6] == 'd' && s[7] == 'l' && s[8] == 'l' && isalpha(s[0]) && isalpha(s[1]) && isalpha(s[9]) && isalpha(s[10]) && isalpha(s[11]) && isalpha(s[12]) && isalpha(s[13])) { + //^^int.dll^^^^^. + return(SCE_BAAN_FUNCTION); + } + else if (sLength > 11 && s[0] == 'i' && s[10] == '.' && isalpha(s[1]) && isalpha(s[2]) && isalpha(s[3]) && isalpha(s[4]) && isalpha(s[5]) && IsADigit(s[6]) && IsADigit(s[7]) && IsADigit(s[8]) && IsADigit(s[9])) { + //i^^^^^####. + return(SCE_BAAN_FUNCTION); + } + + return(SCE_BAAN_DEFAULT); +} + +static bool IsCommentLine(Sci_Position line, LexAccessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (ch == '|' && style == SCE_BAAN_COMMENT) + return true; + else if (!IsASpaceOrTab(ch)) + return false; + } + return false; +} + +static bool IsPreProcLine(Sci_Position line, LexAccessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (ch == '#' && style == SCE_BAAN_PREPROCESSOR) { + if (styler.Match(i, "#elif") || styler.Match(i, "#else") || styler.Match(i, "#endif") + || styler.Match(i, "#if") || styler.Match(i, "#ifdef") || styler.Match(i, "#ifndef")) + // Above PreProcessors has a seperate fold mechanism. + return false; + else + return true; + } + else if (ch == '^') + return true; + else if (!IsASpaceOrTab(ch)) + return false; + } + return false; +} + +static int mainOrSubSectionLine(Sci_Position line, LexAccessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (style == SCE_BAAN_WORD5 || style == SCE_BAAN_WORD4) + return style; + else if (IsASpaceOrTab(ch)) + continue; + else + break; + } + return 0; +} + +static bool priorSectionIsSubSection(Sci_Position line, LexAccessor &styler){ + while (line > 0) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (style == SCE_BAAN_WORD4) + return true; + else if (style == SCE_BAAN_WORD5) + return false; + else if (IsASpaceOrTab(ch)) + continue; + else + break; + } + line--; + } + return false; +} + +static bool nextSectionIsSubSection(Sci_Position line, LexAccessor &styler) { + while (line > 0) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (style == SCE_BAAN_WORD4) + return true; + else if (style == SCE_BAAN_WORD5) + return false; + else if (IsASpaceOrTab(ch)) + continue; + else + break; + } + line++; + } + return false; +} + +static bool IsDeclarationLine(Sci_Position line, LexAccessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (style == SCE_BAAN_WORD) { + if (styler.Match(i, "table") || styler.Match(i, "extern") || styler.Match(i, "long") + || styler.Match(i, "double") || styler.Match(i, "boolean") || styler.Match(i, "string") + || styler.Match(i, "domain")) { + for (Sci_Position j = eol_pos; j > pos; j--) { + int styleFromEnd = styler.StyleAt(j); + if (styleFromEnd == SCE_BAAN_COMMENT) + continue; + else if (IsASpace(styler[j])) + continue; + else if (styler[j] != ',') + //Above conditions ensures, Declaration is not part of any function parameters. + return true; + else + return false; + } + } + else + return false; + } + else if (!IsASpaceOrTab(ch)) + return false; + } + return false; +} + +static bool IsInnerLevelFold(Sci_Position line, LexAccessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (style == SCE_BAAN_WORD && (styler.Match(i, "else" ) || styler.Match(i, "case") + || styler.Match(i, "default") || styler.Match(i, "selectdo") || styler.Match(i, "selecteos") + || styler.Match(i, "selectempty") || styler.Match(i, "selecterror"))) + return true; + else if (IsASpaceOrTab(ch)) + continue; + else + return false; + } + return false; +} + +static inline bool wordInArray(const std::string& value, std::string *array, int length) +{ + for (int i = 0; i < length; i++) + { + if (value == array[i]) + { + return true; + } + } + + return false; +} + +class WordListAbridged : public WordList { +public: + WordListAbridged() { + kwAbridged = false; + kwHasSection = false; + }; + ~WordListAbridged() { + Clear(); + }; + bool kwAbridged; + bool kwHasSection; + bool Contains(const char *s) { + return kwAbridged ? InListAbridged(s, '~') : InList(s); + }; +}; + +} + +class LexerBaan : public DefaultLexer { + WordListAbridged keywords; + WordListAbridged keywords2; + WordListAbridged keywords3; + WordListAbridged keywords4; + WordListAbridged keywords5; + WordListAbridged keywords6; + WordListAbridged keywords7; + WordListAbridged keywords8; + WordListAbridged keywords9; + OptionsBaan options; + OptionSetBaan osBaan; +public: + LexerBaan() : DefaultLexer("baan", SCLEX_BAAN) { + } + + virtual ~LexerBaan() { + } + + int SCI_METHOD Version() const override { + return lvRelease5; + } + + void SCI_METHOD Release() override { + delete this; + } + + const char * SCI_METHOD PropertyNames() override { + return osBaan.PropertyNames(); + } + + int SCI_METHOD PropertyType(const char * name) override { + return osBaan.PropertyType(name); + } + + const char * SCI_METHOD DescribeProperty(const char * name) override { + return osBaan.DescribeProperty(name); + } + + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + + const char * SCI_METHOD PropertyGet(const char *key) override { + return osBaan.PropertyGet(key); + } + + const char * SCI_METHOD DescribeWordListSets() override { + return osBaan.DescribeWordListSets(); + } + + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return NULL; + } + + static ILexer5 * LexerFactoryBaan() { + return new LexerBaan(); + } +}; + +Sci_Position SCI_METHOD LexerBaan::PropertySet(const char *key, const char *val) { + if (osBaan.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerBaan::WordListSet(int n, const char *wl) { + WordListAbridged *WordListAbridgedN = 0; + switch (n) { + case 0: + WordListAbridgedN = &keywords; + break; + case 1: + WordListAbridgedN = &keywords2; + break; + case 2: + WordListAbridgedN = &keywords3; + break; + case 3: + WordListAbridgedN = &keywords4; + break; + case 4: + WordListAbridgedN = &keywords5; + break; + case 5: + WordListAbridgedN = &keywords6; + break; + case 6: + WordListAbridgedN = &keywords7; + break; + case 7: + WordListAbridgedN = &keywords8; + break; + case 8: + WordListAbridgedN = &keywords9; + break; + } + Sci_Position firstModification = -1; + if (WordListAbridgedN) { + WordListAbridged wlNew; + wlNew.Set(wl); + if (*WordListAbridgedN != wlNew) { + WordListAbridgedN->Set(wl); + WordListAbridgedN->kwAbridged = strchr(wl, '~') != NULL; + WordListAbridgedN->kwHasSection = strchr(wl, ':') != NULL; + + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + + if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line + initStyle = SCE_BAAN_DEFAULT; + + int visibleChars = 0; + bool lineHasDomain = false; + bool lineHasFunction = false; + bool lineHasPreProc = false; + bool lineIgnoreString = false; + bool lineHasDefines = false; + bool numberIsHex = false; + char word[1000]; + int wordlen = 0; + + std::string preProcessorTags[13] = { "#context_off", "#context_on", + "#define", "#elif", "#else", "#endif", + "#ident", "#if", "#ifdef", "#ifndef", + "#include", "#pragma", "#undef" }; + LexAccessor styler(pAccess); + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_BAAN_OPERATOR: + sc.SetState(SCE_BAAN_DEFAULT); + break; + case SCE_BAAN_NUMBER: + if (IsASpaceOrTab(sc.ch) || sc.ch == '\r' || sc.ch == '\n' || IsAnOperator(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + else if ((numberIsHex && !(MakeLowerCase(sc.ch) == 'x' || MakeLowerCase(sc.ch) == 'e' || + IsADigit(sc.ch, 16) || sc.ch == '.' || sc.ch == '-' || sc.ch == '+')) || + (!numberIsHex && !(MakeLowerCase(sc.ch) == 'e' || IsADigit(sc.ch) + || sc.ch == '.' || sc.ch == '-' || sc.ch == '+'))) { + // check '-' for possible -10e-5. Add '+' as well. + numberIsHex = false; + sc.ChangeState(SCE_BAAN_IDENTIFIER); + sc.SetState(SCE_BAAN_DEFAULT); + } + break; + case SCE_BAAN_IDENTIFIER: + if (!IsAWordChar(sc.ch)) { + char s[1000]; + char s1[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (sc.ch == ':') { + memcpy(s1, s, sizeof(s)); + s1[sc.LengthCurrent()] = sc.ch; + s1[sc.LengthCurrent() + 1] = '\0'; + } + if ((keywords.kwHasSection && (sc.ch == ':')) ? keywords.Contains(s1) : keywords.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD); + if (0 == strcmp(s, "domain")) { + lineHasDomain = true; + } + else if (0 == strcmp(s, "function")) { + lineHasFunction = true; + } + } + else if (lineHasDomain) { + sc.ChangeState(SCE_BAAN_DOMDEF); + lineHasDomain = false; + } + else if (lineHasFunction) { + sc.ChangeState(SCE_BAAN_FUNCDEF); + lineHasFunction = false; + } + else if ((keywords2.kwHasSection && (sc.ch == ':')) ? keywords2.Contains(s1) : keywords2.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD2); + } + else if ((keywords3.kwHasSection && (sc.ch == ':')) ? keywords3.Contains(s1) : keywords3.Contains(s)) { + if (sc.ch == '(') + sc.ChangeState(SCE_BAAN_WORD3); + else + sc.ChangeState(SCE_BAAN_IDENTIFIER); + } + else if ((keywords4.kwHasSection && (sc.ch == ':')) ? keywords4.Contains(s1) : keywords4.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD4); + } + else if ((keywords5.kwHasSection && (sc.ch == ':')) ? keywords5.Contains(s1) : keywords5.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD5); + } + else if ((keywords6.kwHasSection && (sc.ch == ':')) ? keywords6.Contains(s1) : keywords6.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD6); + } + else if ((keywords7.kwHasSection && (sc.ch == ':')) ? keywords7.Contains(s1) : keywords7.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD7); + } + else if ((keywords8.kwHasSection && (sc.ch == ':')) ? keywords8.Contains(s1) : keywords8.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD8); + } + else if ((keywords9.kwHasSection && (sc.ch == ':')) ? keywords9.Contains(s1) : keywords9.Contains(s)) { + sc.ChangeState(SCE_BAAN_WORD9); + } + else if (lineHasPreProc) { + sc.ChangeState(SCE_BAAN_OBJECTDEF); + lineHasPreProc = false; + } + else if (lineHasDefines) { + sc.ChangeState(SCE_BAAN_DEFINEDEF); + lineHasDefines = false; + } + else { + int state = IsAnyOtherIdentifier(s, sc.LengthCurrent()); + if (state > 0) { + sc.ChangeState(state); + } + } + sc.SetState(SCE_BAAN_DEFAULT); + } + break; + case SCE_BAAN_PREPROCESSOR: + if (options.baanStylingWithinPreprocessor) { + if (IsASpace(sc.ch) || IsAnOperator(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } + else { + if (sc.atLineEnd && (sc.chNext != '^')) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } + break; + case SCE_BAAN_COMMENT: + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_BAAN_DEFAULT); + } + break; + case SCE_BAAN_COMMENTDOC: + if (sc.MatchIgnoreCase("enddllusage")) { + for (unsigned int i = 0; i < 10; i++) { + sc.Forward(); + } + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } + else if (sc.MatchIgnoreCase("endfunctionusage")) { + for (unsigned int i = 0; i < 15; i++) { + sc.Forward(); + } + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } + break; + case SCE_BAAN_STRING: + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } + else if ((sc.atLineEnd) && (sc.chNext != '^')) { + sc.ChangeState(SCE_BAAN_STRINGEOL); + sc.ForwardSetState(SCE_BAAN_DEFAULT); + visibleChars = 0; + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_BAAN_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)) + || ((sc.ch == '-' || sc.ch == '+') && (IsADigit(sc.chNext) || sc.chNext == '.')) + || (MakeLowerCase(sc.ch) == 'e' && (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-'))) { + if ((sc.ch == '0' && MakeLowerCase(sc.chNext) == 'x') || + ((sc.ch == '-' || sc.ch == '+') && sc.chNext == '0' && MakeLowerCase(sc.GetRelativeCharacter(2)) == 'x')){ + numberIsHex = true; + } + sc.SetState(SCE_BAAN_NUMBER); + } + else if (sc.MatchIgnoreCase("dllusage") || sc.MatchIgnoreCase("functionusage")) { + sc.SetState(SCE_BAAN_COMMENTDOC); + do { + sc.Forward(); + } while ((!sc.atLineEnd) && sc.More()); + } + else if (iswordstart(sc.ch)) { + sc.SetState(SCE_BAAN_IDENTIFIER); + } + else if (sc.Match('|')) { + sc.SetState(SCE_BAAN_COMMENT); + } + else if (sc.ch == '\"' && !(lineIgnoreString)) { + sc.SetState(SCE_BAAN_STRING); + } + else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_BAAN_PREPROCESSOR); + word[0] = '\0'; + wordlen = 0; + while (sc.More() && !(IsASpace(sc.chNext) || IsAnOperator(sc.chNext))) { + sc.Forward(); + wordlen++; + } + sc.GetCurrentLowered(word, sizeof(word)); + if (!sc.atLineEnd) { + word[wordlen++] = sc.ch; + word[wordlen++] = '\0'; + } + if (!wordInArray(word, preProcessorTags, 13)) + // Colorise only preprocessor built in Baan. + sc.ChangeState(SCE_BAAN_IDENTIFIER); + if (strcmp(word, "#pragma") == 0 || strcmp(word, "#include") == 0) { + lineHasPreProc = true; + lineIgnoreString = true; + } + else if (strcmp(word, "#define") == 0 || strcmp(word, "#undef") == 0 || + strcmp(word, "#ifdef") == 0 || strcmp(word, "#if") == 0 || strcmp(word, "#ifndef") == 0) { + lineHasDefines = true; + lineIgnoreString = false; + } + } + else if (IsAnOperator(static_cast(sc.ch))) { + sc.SetState(SCE_BAAN_OPERATOR); + } + } + + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lineHasDomain = false; + lineHasFunction = false; + lineHasPreProc = false; + lineIgnoreString = false; + lineHasDefines = false; + numberIsHex = false; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +void SCI_METHOD LexerBaan::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + if (!options.fold) + return; + + char word[100]; + int wordlen = 0; + bool foldStart = true; + bool foldNextSelect = true; + bool afterFunctionSection = false; + bool beforeDeclarationSection = false; + int currLineStyle = 0; + int nextLineStyle = 0; + + std::string startTags[6] = { "for", "if", "on", "repeat", "select", "while" }; + std::string endTags[6] = { "endcase", "endfor", "endif", "endselect", "endwhile", "until" }; + std::string selectCloseTags[5] = { "selectdo", "selecteos", "selectempty", "selecterror", "endselect" }; + + LexAccessor styler(pAccess); + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + + // Backtrack to previous line in case need to fix its fold status + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + + int levelPrev = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelPrev = styler.LevelAt(lineCurrent - 1) >> 16; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int style = initStyle; + int styleNext = styler.StyleAt(startPos); + + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + style = styleNext; + styleNext = styler.StyleAt(i + 1); + int stylePrev = (i) ? styler.StyleAt(i - 1) : SCE_BAAN_DEFAULT; + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + // Comment folding + if (options.foldComment && style == SCE_BAAN_COMMENTDOC) { + if (style != stylePrev) { + levelCurrent++; + } + else if (style != styleNext) { + levelCurrent--; + } + } + if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent + 1, styler)) + levelCurrent--; + } + // PreProcessor Folding + if (options.foldPreprocessor) { + if (atEOL && IsPreProcLine(lineCurrent, styler)) { + if (!IsPreProcLine(lineCurrent - 1, styler) + && IsPreProcLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsPreProcLine(lineCurrent - 1, styler) + && !IsPreProcLine(lineCurrent + 1, styler)) + levelCurrent--; + } + else if (style == SCE_BAAN_PREPROCESSOR) { + // folds #ifdef/#if/#ifndef - they are not part of the IsPreProcLine folding. + if (ch == '#') { + if (styler.Match(i, "#ifdef") || styler.Match(i, "#if") || styler.Match(i, "#ifndef") + || styler.Match(i, "#context_on")) + levelCurrent++; + else if (styler.Match(i, "#endif") || styler.Match(i, "#context_off")) + levelCurrent--; + } + } + } + //Syntax Folding + if (options.baanFoldSyntaxBased && (style == SCE_BAAN_OPERATOR)) { + if (ch == '{' || ch == '(') { + levelCurrent++; + } + else if (ch == '}' || ch == ')') { + levelCurrent--; + } + } + //Keywords Folding + if (options.baanFoldKeywordsBased) { + if (atEOL && IsDeclarationLine(lineCurrent, styler)) { + if (!IsDeclarationLine(lineCurrent - 1, styler) + && IsDeclarationLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsDeclarationLine(lineCurrent - 1, styler) + && !IsDeclarationLine(lineCurrent + 1, styler)) + levelCurrent--; + } + else if (style == SCE_BAAN_WORD) { + word[wordlen++] = static_cast(MakeLowerCase(ch)); + if (wordlen == 100) { // prevent overflow + word[0] = '\0'; + wordlen = 1; + } + if (styleNext != SCE_BAAN_WORD) { + word[wordlen] = '\0'; + wordlen = 0; + if (strcmp(word, "for") == 0) { + Sci_PositionU j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "update")) { + // Means this is a "for update" used by Select which is already folded. + foldStart = false; + } + } + else if (strcmp(word, "on") == 0) { + Sci_PositionU j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (!styler.Match(j, "case")) { + // Means this is not a "on Case" statement... could be "on" used by index. + foldStart = false; + } + } + else if (strcmp(word, "select") == 0) { + if (foldNextSelect) { + // Next Selects are sub-clause till reach of selectCloseTags[] array. + foldNextSelect = false; + foldStart = true; + } + else { + foldNextSelect = false; + foldStart = false; + } + } + else if (wordInArray(word, selectCloseTags, 5)) { + // select clause ends, next select clause can be folded. + foldNextSelect = true; + foldStart = true; + } + else { + foldStart = true; + } + if (foldStart) { + if (wordInArray(word, startTags, 6)) { + levelCurrent++; + } + else if (wordInArray(word, endTags, 6)) { + levelCurrent--; + } + } + } + } + } + // Fold inner level of if/select/case statements + if (options.baanFoldInnerLevel && atEOL) { + bool currLineInnerLevel = IsInnerLevelFold(lineCurrent, styler); + bool nextLineInnerLevel = IsInnerLevelFold(lineCurrent + 1, styler); + if (currLineInnerLevel && currLineInnerLevel != nextLineInnerLevel) { + levelCurrent++; + } + else if (nextLineInnerLevel && nextLineInnerLevel != currLineInnerLevel) { + levelCurrent--; + } + } + // Section Foldings. + // One way of implementing Section Foldings, as there is no END markings of sections. + // first section ends on the previous line of next section. + // Re-written whole folding to accomodate this. + if (options.baanFoldSections && atEOL) { + currLineStyle = mainOrSubSectionLine(lineCurrent, styler); + nextLineStyle = mainOrSubSectionLine(lineCurrent + 1, styler); + if (currLineStyle != 0 && currLineStyle != nextLineStyle) { + if (levelCurrent < levelPrev) + --levelPrev; + for (Sci_Position j = styler.LineStart(lineCurrent); j < styler.LineStart(lineCurrent + 1) - 1; j++) { + if (IsASpaceOrTab(styler[j])) + continue; + else if (styler.StyleAt(j) == SCE_BAAN_WORD5) { + if (styler.Match(j, "functions:")) { + // Means functions: is the end of MainSections. + // Nothing to fold after this. + afterFunctionSection = true; + break; + } + else { + afterFunctionSection = false; + break; + } + } + else { + afterFunctionSection = false; + break; + } + } + if (!afterFunctionSection) + levelCurrent++; + } + else if (nextLineStyle != 0 && currLineStyle != nextLineStyle + && (priorSectionIsSubSection(lineCurrent -1 ,styler) + || !nextSectionIsSubSection(lineCurrent + 1, styler))) { + for (Sci_Position j = styler.LineStart(lineCurrent + 1); j < styler.LineStart(lineCurrent + 1 + 1) - 1; j++) { + if (IsASpaceOrTab(styler[j])) + continue; + else if (styler.StyleAt(j) == SCE_BAAN_WORD5) { + if (styler.Match(j, "declaration:")) { + // Means declaration: is the start of MainSections. + // Nothing to fold before this. + beforeDeclarationSection = true; + break; + } + else { + beforeDeclarationSection = false; + break; + } + } + else { + beforeDeclarationSection = false; + break; + } + } + if (!beforeDeclarationSection) { + levelCurrent--; + if (nextLineStyle == SCE_BAAN_WORD5 && priorSectionIsSubSection(lineCurrent-1, styler)) + // next levelCurrent--; is to unfold previous subsection fold. + // On reaching the next main section, the previous main as well sub section ends. + levelCurrent--; + } + } + } + if (atEOL) { + int lev = levelPrev; + lev |= levelCurrent << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +extern const LexerModule lmBaan(SCLEX_BAAN, LexerBaan::LexerFactoryBaan, "baan", baanWordLists); diff --git a/src/lexilla/lexers/LexBash.cxx b/src/lexilla/lexers/LexBash.cxx new file mode 100644 index 000000000..836cdcb65 --- /dev/null +++ b/src/lexilla/lexers/LexBash.cxx @@ -0,0 +1,1291 @@ +// Scintilla source code edit control +/** @file LexBash.cxx + ** Lexer for Bash. + **/ +// Copyright 2004-2012 by Neil Hodgson +// Adapted from LexPerl by Kein-Hong Man 2004 +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "InList.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SubStyles.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + +#define HERE_DELIM_MAX 256 + +// define this if you want 'invalid octals' to be marked as errors +// usually, this is not a good idea, permissive lexing is better +#undef PEDANTIC_OCTAL + +#define BASH_BASE_ERROR 65 +#define BASH_BASE_DECIMAL 66 +#define BASH_BASE_HEX 67 +#ifdef PEDANTIC_OCTAL +#define BASH_BASE_OCTAL 68 +#define BASH_BASE_OCTAL_ERROR 69 +#endif + +// state constants for parts of a bash command segment +enum class CmdState { + Body, + Start, + Word, + Test, // test + SingleBracket, // [] + DoubleBracket, // [[]] + Arithmetic, + Delimiter, +}; + +enum class CommandSubstitution : int { + Backtick, + Inside, + InsideTrack, +}; + +// state constants for nested delimiter pairs, used by +// SCE_SH_STRING, SCE_SH_PARAM and SCE_SH_BACKTICKS processing +enum class QuoteStyle { + Literal, // '' + CString, // $'' + String, // "" + LString, // $"" + HereDoc, // here document + Backtick, // `` + Parameter, // ${} + Command, // $() + CommandInside, // $() with styling inside + Arithmetic, // $(()), $[] +}; + +#define BASH_QUOTE_STACK_MAX 7 +#define BASH_SPECIAL_PARAMETER "*@#?-$!" + +constexpr int commandSubstitutionFlag = 0x40; +constexpr int MaskCommand(int state) noexcept { + return state & ~commandSubstitutionFlag; +} + +constexpr int translateBashDigit(int ch) noexcept { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 36; + } else if (ch == '@') { + return 62; + } else if (ch == '_') { + return 63; + } + return BASH_BASE_ERROR; +} + +int getBashNumberBase(char *s) noexcept { + int i = 0; + int base = 0; + while (*s) { + base = base * 10 + (*s++ - '0'); + i++; + } + if (base > 64 || i > 2) { + return BASH_BASE_ERROR; + } + return base; +} + +constexpr int opposite(int ch) noexcept { + if (ch == '(') return ')'; + if (ch == '[') return ']'; + if (ch == '{') return '}'; + if (ch == '<') return '>'; + return ch; +} + +int GlobScan(StyleContext &sc) { + // forward scan for zsh globs, disambiguate versus bash arrays + // complex expressions may still fail, e.g. unbalanced () '' "" etc + int c = 0; + int sLen = 0; + int pCount = 0; + int hash = 0; + while ((c = sc.GetRelativeCharacter(++sLen)) != 0) { + if (IsASpace(c)) { + return 0; + } else if (c == '\'' || c == '\"') { + if (hash != 2) return 0; + } else if (c == '#' && hash == 0) { + hash = (sLen == 1) ? 2:1; + } else if (c == '(') { + pCount++; + } else if (c == ')') { + if (pCount == 0) { + if (hash) return sLen; + return 0; + } + pCount--; + } + } + return 0; +} + +bool IsCommentLine(Sci_Position line, LexAccessor &styler) { + const Sci_Position pos = styler.LineStart(line); + const Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + const char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +constexpr bool StyleForceBacktrack(int state) noexcept { + return AnyOf(state, SCE_SH_CHARACTER, SCE_SH_STRING, SCE_SH_BACKTICKS, SCE_SH_HERE_Q, SCE_SH_PARAM); +} + +struct OptionsBash { + bool fold = false; + bool foldComment = false; + bool foldCompact = true; + bool stylingInsideString = false; + bool stylingInsideBackticks = false; + bool stylingInsideParameter = false; + bool stylingInsideHeredoc = false; + bool nestedBackticks = true; + CommandSubstitution commandSubstitution = CommandSubstitution::Backtick; + std::string specialParameter = BASH_SPECIAL_PARAMETER; + + [[nodiscard]] bool stylingInside(int state) const noexcept { + switch (state) { + case SCE_SH_STRING: + return stylingInsideString; + case SCE_SH_BACKTICKS: + return stylingInsideBackticks; + case SCE_SH_PARAM: + return stylingInsideParameter; + case SCE_SH_HERE_Q: + return stylingInsideHeredoc; + default: + return false; + } + } +}; + +const char * const bashWordListDesc[] = { + "Keywords", + nullptr +}; + +struct OptionSetBash : public OptionSet { + OptionSetBash() { + DefineProperty("fold", &OptionsBash::fold); + + DefineProperty("fold.comment", &OptionsBash::foldComment); + + DefineProperty("fold.compact", &OptionsBash::foldCompact); + + DefineProperty("lexer.bash.styling.inside.string", &OptionsBash::stylingInsideString, + "Set this property to 1 to highlight shell expansions inside string."); + + DefineProperty("lexer.bash.styling.inside.backticks", &OptionsBash::stylingInsideBackticks, + "Set this property to 1 to highlight shell expansions inside backticks."); + + DefineProperty("lexer.bash.styling.inside.parameter", &OptionsBash::stylingInsideParameter, + "Set this property to 1 to highlight shell expansions inside ${} parameter expansion."); + + DefineProperty("lexer.bash.styling.inside.heredoc", &OptionsBash::stylingInsideHeredoc, + "Set this property to 1 to highlight shell expansions inside here document."); + + DefineProperty("lexer.bash.command.substitution", &OptionsBash::commandSubstitution, + "Set how to highlight $() command substitution. " + "0 (the default) highlighted as backticks. " + "1 highlighted inside. " + "2 highlighted inside with extra scope tracking."); + + DefineProperty("lexer.bash.nested.backticks", &OptionsBash::nestedBackticks, + "Set this property to 0 to disable nested backquoted command substitution."); + + DefineProperty("lexer.bash.special.parameter", &OptionsBash::specialParameter, + "Set shell (default is Bash) special parameters."); + + DefineWordListSets(bashWordListDesc); + } +}; + +class QuoteCls { // Class to manage quote pairs (simplified vs LexPerl) +public: + int Count = 0; + int Up = '\0'; + int Down = '\0'; + QuoteStyle Style = QuoteStyle::Literal; + int Outer = SCE_SH_DEFAULT; + CmdState State = CmdState::Body; + void Clear() noexcept { + Count = 0; + Up = '\0'; + Down = '\0'; + Style = QuoteStyle::Literal; + Outer = SCE_SH_DEFAULT; + State = CmdState::Body; + } + void Start(int u, QuoteStyle s, int outer, CmdState state) noexcept { + Count = 1; + Up = u; + Down = opposite(Up); + Style = s; + Outer = outer; + State = state; + } +}; + +class QuoteStackCls { // Class to manage quote pairs that nest +public: + int Depth = 0; + int State = SCE_SH_DEFAULT; + bool lineContinuation = false; + bool nestedBackticks = false; + CommandSubstitution commandSubstitution = CommandSubstitution::Backtick; + int insideCommand = 0; + unsigned backtickLevel = 0; + QuoteCls Current; + QuoteCls Stack[BASH_QUOTE_STACK_MAX]; + const CharacterSet &setParamStart; + QuoteStackCls(const CharacterSet &setParamStart_) noexcept : setParamStart{setParamStart_} {} + [[nodiscard]] bool Empty() const noexcept { + return Current.Up == '\0'; + } + void Start(int u, QuoteStyle s, int outer, CmdState state) noexcept { + if (Empty()) { + Current.Start(u, s, outer, state); + if (s == QuoteStyle::Backtick) { + ++backtickLevel; + } + } else { + Push(u, s, outer, state); + } + } + void Push(int u, QuoteStyle s, int outer, CmdState state) noexcept { + if (Depth >= BASH_QUOTE_STACK_MAX) { + return; + } + Stack[Depth] = Current; + Depth++; + Current.Start(u, s, outer, state); + if (s == QuoteStyle::Backtick) { + ++backtickLevel; + } + } + void Pop() noexcept { + if (Depth == 0) { + Clear(); + return; + } + if (backtickLevel != 0 && Current.Style == QuoteStyle::Backtick) { + --backtickLevel; + } + if (insideCommand != 0 && Current.Style == QuoteStyle::CommandInside) { + insideCommand = 0; + for (int i = 0; i < Depth; i++) { + if (Stack[i].Style == QuoteStyle::CommandInside) { + insideCommand = commandSubstitutionFlag; + break; + } + } + } + Depth--; + Current = Stack[Depth]; + } + void Clear() noexcept { + Depth = 0; + State = SCE_SH_DEFAULT; + insideCommand = 0; + backtickLevel = 0; + Current.Clear(); + } + bool CountDown(StyleContext &sc, CmdState &cmdState) { + Current.Count--; + while (Current.Count > 0 && sc.chNext == Current.Down) { + Current.Count--; + sc.Forward(); + } + if (Current.Count == 0) { + cmdState = Current.State; + const int outer = Current.Outer; + Pop(); + sc.ForwardSetState(outer | insideCommand); + return true; + } + return false; + } + void Expand(StyleContext &sc, CmdState &cmdState, bool stylingInside) { + const CmdState current = cmdState; + const int state = sc.state; + QuoteStyle style = QuoteStyle::Literal; + State = state; + sc.SetState(SCE_SH_SCALAR); + sc.Forward(); + if (sc.ch == '{') { + style = QuoteStyle::Parameter; + sc.ChangeState(SCE_SH_PARAM); + } else if (sc.ch == '\'') { + style = QuoteStyle::CString; + sc.ChangeState(SCE_SH_STRING); + } else if (sc.ch == '"') { + style = QuoteStyle::LString; + sc.ChangeState(SCE_SH_STRING); + } else if (sc.ch == '(' || sc.ch == '[') { + if (sc.ch == '[' || sc.chNext == '(') { + style = QuoteStyle::Arithmetic; + cmdState = CmdState::Arithmetic; + sc.ChangeState(SCE_SH_OPERATOR); + } else { + if (stylingInside && commandSubstitution >= CommandSubstitution::Inside) { + style = QuoteStyle::CommandInside; + cmdState = CmdState::Delimiter; + sc.ChangeState(SCE_SH_OPERATOR); + if (commandSubstitution == CommandSubstitution::InsideTrack) { + insideCommand = commandSubstitutionFlag; + } + } else { + style = QuoteStyle::Command; + sc.ChangeState(SCE_SH_BACKTICKS); + } + } + } else { + // scalar has no delimiter pair + if (!setParamStart.Contains(sc.ch)) { + stylingInside = false; // not scalar + } + } + if (!stylingInside) { + sc.ChangeState(state); + } else { + sc.ChangeState(sc.state | insideCommand); + } + if (style != QuoteStyle::Literal) { + Start(sc.ch, style, state, current); + sc.Forward(); + } + } + void Escape(StyleContext &sc) { + unsigned count = 1; + while (sc.chNext == '\\') { + ++count; + sc.Forward(); + } + bool escaped = count & 1U; // odd backslash escape next character + if (escaped && (sc.chNext == '\r' || sc.chNext == '\n')) { + lineContinuation = true; + if (sc.state == SCE_SH_IDENTIFIER) { + sc.SetState(SCE_SH_OPERATOR | insideCommand); + } + return; + } + if (backtickLevel > 0 && nestedBackticks) { + /* + for $k$ level substitution with $N$ backslashes: + * when $N/2^k$ is odd, following dollar is escaped. + * when $(N - 1)/2^k$ is even, following quote is escaped. + * when $N = n\times 2^{k + 1} - 1$, following backtick is escaped. + * when $N = n\times 2^{k + 1} + 2^k - 1$, following backtick starts inner substitution. + * when $N = m\times 2^k + 2^{k - 1} - 1$ and $k > 1$, following backtick ends current substitution. + */ + if (sc.chNext == '$') { + escaped = (count >> backtickLevel) & 1U; + } else if (sc.chNext == '\"' || sc.chNext == '\'') { + escaped = (((count - 1) >> backtickLevel) & 1U) == 0; + } else if (sc.chNext == '`' && escaped) { + unsigned mask = 1U << (backtickLevel + 1); + count += 1; + escaped = (count & (mask - 1)) == 0; + if (!escaped) { + unsigned remain = count - (mask >> 1U); + if (static_cast(remain) >= 0 && (remain & (mask - 1)) == 0) { + escaped = true; + ++backtickLevel; + } else if (backtickLevel > 1) { + mask >>= 1U; + remain = count - (mask >> 1U); + if (static_cast(remain) >= 0 && (remain & (mask - 1)) == 0) { + escaped = true; + --backtickLevel; + } + } + } + } + } + if (escaped) { + sc.Forward(); + } + } +}; + +const char styleSubable[] = { SCE_SH_IDENTIFIER, SCE_SH_SCALAR, 0 }; + +const LexicalClass lexicalClasses[] = { + // Lexer Bash SCLEX_BASH SCE_SH_: + 0, "SCE_SH_DEFAULT", "default", "White space", + 1, "SCE_SH_ERROR", "error", "Error", + 2, "SCE_SH_COMMENTLINE", "comment line", "Line comment: #", + 3, "SCE_SH_NUMBER", "literal numeric", "Number", + 4, "SCE_SH_WORD", "keyword", "Keyword", + 5, "SCE_SH_STRING", "literal string", "String", + 6, "SCE_SH_CHARACTER", "literal string", "Single quoted string", + 7, "SCE_SH_OPERATOR", "operator", "Operators", + 8, "SCE_SH_IDENTIFIER", "identifier", "Identifiers", + 9, "SCE_SH_SCALAR", "identifier", "Scalar variable", + 10, "SCE_SH_PARAM", "identifier", "Parameter", + 11, "SCE_SH_BACKTICKS", "literal string", "Backtick quoted command", + 12, "SCE_SH_HERE_DELIM", "operator", "Heredoc delimiter", + 13, "SCE_SH_HERE_Q", "here-doc literal string", "Heredoc quoted string", +}; + +} + +class LexerBash final : public DefaultLexer { + WordList keywords; + WordList cmdDelimiter; + WordList bashStruct; + WordList bashStruct_in; + WordList testOperator; + OptionsBash options; + OptionSetBash osBash; + CharacterSet setParamStart; + enum { ssIdentifier, ssScalar }; + SubStyles subStyles{styleSubable}; +public: + LexerBash() : + DefaultLexer("bash", SCLEX_BASH, lexicalClasses, std::size(lexicalClasses)), + setParamStart(CharacterSet::setAlphaNum, "_" BASH_SPECIAL_PARAMETER) { + cmdDelimiter.Set("| || |& & && ; ;; ( ) { }"); + bashStruct.Set("if elif fi while until else then do done esac eval"); + bashStruct_in.Set("for case select"); + testOperator.Set("eq ge gt le lt ne ef nt ot"); + } + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char * SCI_METHOD PropertyNames() override { + return osBash.PropertyNames(); + } + int SCI_METHOD PropertyType(const char* name) override { + return osBash.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osBash.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char* key) override { + return osBash.PropertyGet(key); + } + const char * SCI_METHOD DescribeWordListSets() override { + return osBash.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos_, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return nullptr; + } + + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) override { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) override { + return subStyles.Length(styleBase); + } + int SCI_METHOD StyleFromSubStyle(int subStyle) override { + const int styleBase = subStyles.BaseStyle(subStyle); + return styleBase; + } + int SCI_METHOD PrimaryStyleFromStyle(int style) override { + return style; + } + void SCI_METHOD FreeSubStyles() override { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override { + subStyles.SetIdentifiers(style, identifiers); + } + int SCI_METHOD DistanceToSecondaryStyles() override { + return 0; + } + const char *SCI_METHOD GetSubStyleBases() override { + return styleSubable; + } + + bool IsTestOperator(const char *s, const CharacterSet &setSingleCharOp) const noexcept { + return (s[2] == '\0' && setSingleCharOp.Contains(s[1])) + || testOperator.InList(s + 1); + } + + static ILexer5 *LexerFactoryBash() { + return new LexerBash(); + } +}; + +Sci_Position SCI_METHOD LexerBash::PropertySet(const char *key, const char *val) { + if (osBash.PropertySet(&options, key, val)) { + if (strcmp(key, "lexer.bash.special.parameter") == 0) { + setParamStart = CharacterSet(CharacterSet::setAlphaNum, "_"); + setParamStart.AddString(options.specialParameter.empty() ? BASH_SPECIAL_PARAMETER : options.specialParameter.c_str()); + } + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerBash::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + switch (n) { + case 0: + wordListN = &keywords; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + if (wordListN->Set(wl)) { + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerBash::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + const CharacterSet setWordStart(CharacterSet::setAlpha, "_"); + // note that [+-] are often parts of identifiers in shell scripts + const CharacterSet setWord(CharacterSet::setAlphaNum, "._+-"); + CharacterSet setMetaCharacter(CharacterSet::setNone, "|&;()<> \t\r\n"); + setMetaCharacter.Add(0); + const CharacterSet setBashOperator(CharacterSet::setNone, "^&%()-+=|{}[]:;>,*/(ch); + Delimiter[DelimiterLength] = '\0'; + } + }; + HereDocCls HereDoc; + + QuoteStackCls QuoteStack(setParamStart); + QuoteStack.nestedBackticks = options.nestedBackticks; + QuoteStack.commandSubstitution = options.commandSubstitution; + + const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_SH_IDENTIFIER); + const WordClassifier &classifierScalars = subStyles.Classifier(SCE_SH_SCALAR); + + int numBase = 0; + int digit = 0; + const Sci_PositionU endPos = startPos + length; + CmdState cmdState = CmdState::Start; + LexAccessor styler(pAccess); + + // Always backtracks to the start of a line that is not a continuation + // of the previous line (i.e. start of a bash command segment) + Sci_Position ln = styler.GetLine(startPos); + if (ln > 0 && startPos == static_cast(styler.LineStart(ln))) + ln--; + for (;;) { + startPos = styler.LineStart(ln); + if (ln == 0 || styler.GetLineState(ln) == static_cast(CmdState::Start)) + break; + ln--; + } + initStyle = SCE_SH_DEFAULT; + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + while (sc.More()) { + + // handle line continuation, updates per-line stored state + if (sc.atLineStart) { + CmdState state = CmdState::Body; // force backtrack while retaining cmdState + if (!StyleForceBacktrack(MaskCommand(sc.state))) { + // retain last line's state + // arithmetic expression and double bracket test can span multiline without line continuation + if (!QuoteStack.lineContinuation && !AnyOf(cmdState, CmdState::DoubleBracket, CmdState::Arithmetic)) { + cmdState = CmdState::Start; + } + if (QuoteStack.Empty()) { // force backtrack when nesting + state = cmdState; + } + } + QuoteStack.lineContinuation = false; + styler.SetLineState(sc.currentLine, static_cast(state)); + } + + // controls change of cmdState at the end of a non-whitespace element + // states Body|Test|Arithmetic persist until the end of a command segment + // state Word persist, but ends with 'in' or 'do' construct keywords + CmdState cmdStateNew = CmdState::Body; + if (cmdState >= CmdState::Word && cmdState <= CmdState::Arithmetic) + cmdStateNew = cmdState; + const int stylePrev = MaskCommand(sc.state); + const int insideCommand = QuoteStack.insideCommand; + + // Determine if the current state should terminate. + switch (MaskCommand(sc.state)) { + case SCE_SH_OPERATOR: + sc.SetState(SCE_SH_DEFAULT | insideCommand); + if (cmdState == CmdState::Delimiter) // if command delimiter, start new command + cmdStateNew = CmdState::Start; + else if (sc.chPrev == '\\') // propagate command state if line continued + cmdStateNew = cmdState; + break; + case SCE_SH_WORD: + // "." never used in Bash variable names but used in file names + if (!setWord.Contains(sc.ch) || sc.Match('+', '=') || sc.Match('.', '.')) { + char s[500]; + sc.GetCurrent(s, sizeof(s)); + int identifierStyle = SCE_SH_IDENTIFIER | insideCommand; + const int subStyle = classifierIdentifiers.ValueFor(s); + if (subStyle >= 0) { + identifierStyle = subStyle | insideCommand; + } + // allow keywords ending in a whitespace, meta character or command delimiter + char s2[10]; + s2[0] = static_cast(sc.ch); + s2[1] = '\0'; + const bool keywordEnds = IsASpace(sc.ch) || setMetaCharacter.Contains(sc.ch) || cmdDelimiter.InList(s2); + // 'in' or 'do' may be construct keywords + if (cmdState == CmdState::Word) { + if (strcmp(s, "in") == 0 && keywordEnds) + cmdStateNew = CmdState::Body; + else if (strcmp(s, "do") == 0 && keywordEnds) + cmdStateNew = CmdState::Start; + else + sc.ChangeState(identifierStyle); + sc.SetState(SCE_SH_DEFAULT | insideCommand); + break; + } + // a 'test' keyword starts a test expression + if (strcmp(s, "test") == 0) { + if (cmdState == CmdState::Start && keywordEnds) { + cmdStateNew = CmdState::Test; + } else + sc.ChangeState(identifierStyle); + } + // detect bash construct keywords + else if (bashStruct.InList(s)) { + if (cmdState == CmdState::Start && keywordEnds) + cmdStateNew = CmdState::Start; + else + sc.ChangeState(identifierStyle); + } + // 'for'|'case'|'select' needs 'in'|'do' to be highlighted later + else if (bashStruct_in.InList(s)) { + if (cmdState == CmdState::Start && keywordEnds) + cmdStateNew = CmdState::Word; + else + sc.ChangeState(identifierStyle); + } + // disambiguate option items and file test operators + else if (s[0] == '-') { + if (!AnyOf(cmdState, CmdState::Test, CmdState::SingleBracket, CmdState::DoubleBracket) + || !keywordEnds || !IsTestOperator(s, setSingleCharOp)) + sc.ChangeState(identifierStyle); + } + // disambiguate keywords and identifiers + else if (cmdState != CmdState::Start + || !(keywords.InList(s) && keywordEnds)) { + sc.ChangeState(identifierStyle); + } + sc.SetState(SCE_SH_DEFAULT | insideCommand); + } + break; + case SCE_SH_IDENTIFIER: + if (!setWord.Contains(sc.ch) || + (cmdState == CmdState::Arithmetic && !setWordStart.Contains(sc.ch))) { + char s[500]; + sc.GetCurrent(s, sizeof(s)); + const int subStyle = classifierIdentifiers.ValueFor(s); + if (subStyle >= 0) { + sc.ChangeState(subStyle | insideCommand); + } + sc.SetState(SCE_SH_DEFAULT | insideCommand); + } + break; + case SCE_SH_NUMBER: + digit = translateBashDigit(sc.ch); + if (numBase == BASH_BASE_DECIMAL) { + if (sc.ch == '#') { + char s[10]; + sc.GetCurrent(s, sizeof(s)); + numBase = getBashNumberBase(s); + if (numBase != BASH_BASE_ERROR) + break; + } else if (IsADigit(sc.ch)) + break; + } else if (numBase == BASH_BASE_HEX) { + if (IsADigit(sc.ch, 16)) + break; +#ifdef PEDANTIC_OCTAL + } else if (numBase == BASH_BASE_OCTAL || + numBase == BASH_BASE_OCTAL_ERROR) { + if (digit <= 7) + break; + if (digit <= 9) { + numBase = BASH_BASE_OCTAL_ERROR; + break; + } +#endif + } else if (numBase == BASH_BASE_ERROR) { + if (digit <= 9) + break; + } else { // DD#DDDD number style handling + if (digit != BASH_BASE_ERROR) { + if (numBase <= 36) { + // case-insensitive if base<=36 + if (digit >= 36) digit -= 26; + } + if (digit < numBase) + break; + if (digit <= 9) { + numBase = BASH_BASE_ERROR; + break; + } + } + } + // fallthrough when number is at an end or error + if (numBase == BASH_BASE_ERROR +#ifdef PEDANTIC_OCTAL + || numBase == BASH_BASE_OCTAL_ERROR +#endif + ) { + sc.ChangeState(SCE_SH_ERROR | insideCommand); + } else if (digit < 62 || digit == 63 || (cmdState != CmdState::Arithmetic && + (sc.ch == '-' || (sc.ch == '.' && sc.chNext != '.')))) { + // current character is alpha numeric, underscore, hyphen or dot + sc.ChangeState(SCE_SH_IDENTIFIER | insideCommand); + break; + } + sc.SetState(SCE_SH_DEFAULT | insideCommand); + break; + case SCE_SH_COMMENTLINE: + if (sc.MatchLineEnd()) { + sc.SetState(SCE_SH_DEFAULT | insideCommand); + } + break; + case SCE_SH_HERE_DELIM: + // From Bash info: + // --------------- + // Specifier format is: <<[-]WORD + // Optional '-' is for removal of leading tabs from here-doc. + // Whitespace acceptable after <<[-] operator + // + if (HereDoc.State == 0) { // '<<' encountered + HereDoc.Quote = sc.chNext; + HereDoc.Quoted = false; + HereDoc.Escaped = false; + HereDoc.BackslashCount = 0; + HereDoc.DelimiterLength = 0; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + if (sc.chNext == '\'' || sc.chNext == '\"') { // a quoted here-doc delimiter (' or ") + sc.Forward(); + HereDoc.Quoted = true; + HereDoc.State = 1; + } else if (setHereDoc.Contains(sc.chNext) || + (sc.chNext == '=' && cmdState != CmdState::Arithmetic)) { + // an unquoted here-doc delimiter, no special handling + HereDoc.State = 1; + } else if (sc.chNext == '<') { // HERE string <<< + sc.Forward(); + sc.ForwardSetState(SCE_SH_DEFAULT | insideCommand); + } else if (IsASpace(sc.chNext)) { + // eat whitespace + } else if (setLeftShift.Contains(sc.chNext) || + (sc.chNext == '=' && cmdState == CmdState::Arithmetic)) { + // left shift <<$var or <<= cases + sc.ChangeState(SCE_SH_OPERATOR | insideCommand); + sc.ForwardSetState(SCE_SH_DEFAULT | insideCommand); + } else { + // symbols terminates; deprecated zero-length delimiter + HereDoc.State = 1; + } + } else if (HereDoc.State == 1) { // collect the delimiter + // * if single quoted, there's no escape + // * if double quoted, there are \\ and \" escapes + if (HereDoc.Quoted && sc.ch == HereDoc.Quote && (HereDoc.BackslashCount & 1) == 0) { // closing quote => end of delimiter + sc.ForwardSetState(SCE_SH_DEFAULT | insideCommand); + } else if (sc.ch == '\\' && HereDoc.Quote != '\'') { + HereDoc.Escaped = true; + HereDoc.BackslashCount += 1; + if ((HereDoc.BackslashCount & 1) == 0 || (HereDoc.Quoted && !AnyOf(sc.chNext, '\"', '\\'))) { + // in quoted prefixes only \ and the quote eat the escape + HereDoc.Append(sc.ch); + } else { + // skip escape prefix + } + } else if (HereDoc.Quoted || setHereDoc2.Contains(sc.ch) || (sc.ch > 32 && sc.ch < 127 && (HereDoc.BackslashCount & 1) != 0)) { + HereDoc.BackslashCount = 0; + HereDoc.Append(sc.ch); + } else { + sc.SetState(SCE_SH_DEFAULT | insideCommand); + } + if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup + sc.SetState(SCE_SH_ERROR | insideCommand); + HereDoc.State = 0; + } + } + break; + case SCE_SH_SCALAR: // variable names + if (!setParam.Contains(sc.ch)) { + char s[500]; + sc.GetCurrent(s, sizeof(s)); + const int subStyle = classifierScalars.ValueFor(&s[1]); // skip the $ + if (subStyle >= 0) { + sc.ChangeState(subStyle | insideCommand); + } + if (sc.LengthCurrent() == 1) { + // Special variable + sc.Forward(); + } + sc.SetState(QuoteStack.State | insideCommand); + continue; + } + break; + case SCE_SH_HERE_Q: + // HereDoc.State == 2 + if (sc.atLineStart && QuoteStack.Current.Style == QuoteStyle::HereDoc) { + sc.SetState(SCE_SH_HERE_Q | insideCommand); + if (HereDoc.Indent) { // tabulation prefix + while (sc.ch == '\t') { + sc.Forward(); + } + } + if ((static_cast(sc.currentPos + HereDoc.DelimiterLength) == sc.lineEnd) && + (HereDoc.DelimiterLength == 0 || sc.Match(HereDoc.Delimiter))) { + if (HereDoc.DelimiterLength != 0) { + sc.SetState(SCE_SH_HERE_DELIM | insideCommand); + while (!sc.MatchLineEnd()) { + sc.Forward(); + } + } + QuoteStack.Pop(); + sc.SetState(SCE_SH_DEFAULT | QuoteStack.insideCommand); + break; + } + } + if (HereDoc.Quoted || HereDoc.Escaped) { + break; + } + // fall through to handle nested shell expansions + [[fallthrough]]; + case SCE_SH_STRING: // delimited styles, can nest + case SCE_SH_PARAM: // ${parameter} + case SCE_SH_BACKTICKS: + if (sc.ch == '\\') { + if (QuoteStack.Current.Style != QuoteStyle::Literal) + QuoteStack.Escape(sc); + } else if (sc.ch == QuoteStack.Current.Down) { + if (QuoteStack.CountDown(sc, cmdState)) { + continue; + } + } else if (sc.ch == QuoteStack.Current.Up) { + if (QuoteStack.Current.Style != QuoteStyle::Parameter) { + QuoteStack.Current.Count++; + } + } else { + if (QuoteStack.Current.Style == QuoteStyle::String || + QuoteStack.Current.Style == QuoteStyle::HereDoc || + QuoteStack.Current.Style == QuoteStyle::LString + ) { // do nesting for "string", $"locale-string", heredoc + const bool stylingInside = options.stylingInside(MaskCommand(sc.state)); + if (sc.ch == '`') { + QuoteStack.Push(sc.ch, QuoteStyle::Backtick, sc.state, cmdState); + if (stylingInside) { + sc.SetState(SCE_SH_BACKTICKS | insideCommand); + } + } else if (sc.ch == '$' && !AnyOf(sc.chNext, '\"', '\'')) { + QuoteStack.Expand(sc, cmdState, stylingInside); + continue; + } + } else if (QuoteStack.Current.Style == QuoteStyle::Command || + QuoteStack.Current.Style == QuoteStyle::Parameter || + QuoteStack.Current.Style == QuoteStyle::Backtick + ) { // do nesting for $(command), `command`, ${parameter} + const bool stylingInside = options.stylingInside(MaskCommand(sc.state)); + if (sc.ch == '\'') { + if (stylingInside) { + QuoteStack.State = sc.state; + sc.SetState(SCE_SH_CHARACTER | insideCommand); + } else { + QuoteStack.Push(sc.ch, QuoteStyle::Literal, sc.state, cmdState); + } + } else if (sc.ch == '\"') { + QuoteStack.Push(sc.ch, QuoteStyle::String, sc.state, cmdState); + if (stylingInside) { + sc.SetState(SCE_SH_STRING | insideCommand); + } + } else if (sc.ch == '`') { + QuoteStack.Push(sc.ch, QuoteStyle::Backtick, sc.state, cmdState); + if (stylingInside) { + sc.SetState(SCE_SH_BACKTICKS | insideCommand); + } + } else if (sc.ch == '$') { + QuoteStack.Expand(sc, cmdState, stylingInside); + continue; + } + } + } + break; + case SCE_SH_CHARACTER: // singly-quoted strings + if (sc.ch == '\'') { + sc.ForwardSetState(QuoteStack.State | insideCommand); + continue; + } + break; + } + + // Must check end of HereDoc state 1 before default state is handled + if (HereDoc.State == 1 && sc.MatchLineEnd()) { + // Begin of here-doc (the line after the here-doc delimiter): + // Lexically, the here-doc starts from the next line after the >>, but the + // first line of here-doc seem to follow the style of the last EOL sequence + HereDoc.State = 2; + if (HereDoc.Quoted) { + if (MaskCommand(sc.state) == SCE_SH_HERE_DELIM) { + // Missing quote at end of string! Syntax error in bash 4.3 + // Mark this bit as an error, do not colour any here-doc + sc.ChangeState(SCE_SH_ERROR | insideCommand); + sc.SetState(SCE_SH_DEFAULT | insideCommand); + } else { + // HereDoc.Quote always == '\'' + sc.SetState(SCE_SH_HERE_Q | insideCommand); + QuoteStack.Start(-1, QuoteStyle::HereDoc, SCE_SH_DEFAULT, cmdState); + } + } else if (HereDoc.DelimiterLength == 0) { + // no delimiter, illegal (but '' and "" are legal) + sc.ChangeState(SCE_SH_ERROR | insideCommand); + sc.SetState(SCE_SH_DEFAULT | insideCommand); + } else { + sc.SetState(SCE_SH_HERE_Q | insideCommand); + QuoteStack.Start(-1, QuoteStyle::HereDoc, SCE_SH_DEFAULT, cmdState); + } + } + + // update cmdState about the current command segment + if (stylePrev != SCE_SH_DEFAULT && MaskCommand(sc.state) == SCE_SH_DEFAULT) { + cmdState = cmdStateNew; + } + // Determine if a new state should be entered. + if (MaskCommand(sc.state) == SCE_SH_DEFAULT) { + if (sc.ch == '\\') { + // Bash can escape any non-newline as a literal + sc.SetState(SCE_SH_IDENTIFIER | insideCommand); + QuoteStack.Escape(sc); + } else if (IsADigit(sc.ch)) { + sc.SetState(SCE_SH_NUMBER | insideCommand); + numBase = BASH_BASE_DECIMAL; + if (sc.ch == '0') { // hex,octal + if (sc.chNext == 'x' || sc.chNext == 'X') { + numBase = BASH_BASE_HEX; + sc.Forward(); + } else if (IsADigit(sc.chNext)) { +#ifdef PEDANTIC_OCTAL + numBase = BASH_BASE_OCTAL; +#endif + } + } + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(((cmdState == CmdState::Arithmetic)? SCE_SH_IDENTIFIER : SCE_SH_WORD) | insideCommand); + } else if (sc.ch == '#') { + if (stylePrev != SCE_SH_WORD && stylePrev != SCE_SH_IDENTIFIER && + (sc.currentPos == 0 || setMetaCharacter.Contains(sc.chPrev))) { + sc.SetState(SCE_SH_COMMENTLINE | insideCommand); + } else { + sc.SetState(SCE_SH_WORD | insideCommand); + } + // handle some zsh features within arithmetic expressions only + if (cmdState == CmdState::Arithmetic) { + if (sc.chPrev == '[') { // [#8] [##8] output digit setting + sc.SetState(SCE_SH_WORD | insideCommand); + if (sc.chNext == '#') { + sc.Forward(); + } + } else if (sc.Match("##^") && IsUpperCase(sc.GetRelative(3))) { // ##^A + sc.SetState(SCE_SH_IDENTIFIER | insideCommand); + sc.Forward(3); + } else if (sc.chNext == '#' && !IsASpace(sc.GetRelative(2))) { // ##a + sc.SetState(SCE_SH_IDENTIFIER | insideCommand); + sc.Forward(2); + } else if (setWordStart.Contains(sc.chNext)) { // #name + sc.SetState(SCE_SH_IDENTIFIER | insideCommand); + } + } + } else if (sc.ch == '\"') { + sc.SetState(SCE_SH_STRING | insideCommand); + QuoteStack.Start(sc.ch, QuoteStyle::String, SCE_SH_DEFAULT, cmdState); + } else if (sc.ch == '\'') { + QuoteStack.State = SCE_SH_DEFAULT; + sc.SetState(SCE_SH_CHARACTER | insideCommand); + } else if (sc.ch == '`') { + sc.SetState(SCE_SH_BACKTICKS | insideCommand); + QuoteStack.Start(sc.ch, QuoteStyle::Backtick, SCE_SH_DEFAULT, cmdState); + } else if (sc.ch == '$') { + QuoteStack.Expand(sc, cmdState, true); + continue; + } else if (cmdState != CmdState::Arithmetic && sc.Match('<', '<')) { + sc.SetState(SCE_SH_HERE_DELIM | insideCommand); + HereDoc.State = 0; + if (sc.GetRelative(2) == '-') { // <<- indent case + HereDoc.Indent = true; + sc.Forward(); + } else { + HereDoc.Indent = false; + } + } else if (sc.ch == '-' && // test operator or short and long option + cmdState != CmdState::Arithmetic && + sc.chPrev != '~' && !IsADigit(sc.chNext)) { + if (IsASpace(sc.chPrev) || setMetaCharacter.Contains(sc.chPrev)) { + sc.SetState(SCE_SH_WORD | insideCommand); + } else { + sc.SetState(SCE_SH_IDENTIFIER | insideCommand); + } + } else if (setBashOperator.Contains(sc.ch)) { + bool isCmdDelim = false; + sc.SetState(SCE_SH_OPERATOR | insideCommand); + // arithmetic expansion and command substitution + if (QuoteStack.Current.Style == QuoteStyle::Arithmetic || QuoteStack.Current.Style == QuoteStyle::CommandInside) { + if (sc.ch == QuoteStack.Current.Down) { + if (QuoteStack.CountDown(sc, cmdState)) { + continue; + } + } else if (sc.ch == QuoteStack.Current.Up) { + QuoteStack.Current.Count++; + } + } + // globs have no whitespace, do not appear in arithmetic expressions + if (cmdState != CmdState::Arithmetic && sc.ch == '(' && sc.chNext != '(') { + const int i = GlobScan(sc); + if (i > 1) { + sc.SetState(SCE_SH_IDENTIFIER | insideCommand); + sc.Forward(i + 1); + continue; + } + } + // handle opening delimiters for test/arithmetic expressions - ((,[[,[ + if (cmdState == CmdState::Start + || cmdState == CmdState::Body) { + if (sc.Match('(', '(')) { + cmdState = CmdState::Arithmetic; + sc.Forward(); + } else if (sc.Match('[', '[') && IsASpace(sc.GetRelative(2))) { + cmdState = CmdState::DoubleBracket; + sc.Forward(); + } else if (sc.ch == '[' && IsASpace(sc.chNext)) { + cmdState = CmdState::SingleBracket; + } + } + // special state -- for ((x;y;z)) in ... looping + if (cmdState == CmdState::Word && sc.Match('(', '(')) { + cmdState = CmdState::Arithmetic; + sc.Forward(2); + continue; + } + // handle command delimiters in command Start|Body|Word state, also Test if 'test' or '[]' + if (cmdState < CmdState::DoubleBracket) { + char s[10]; + s[0] = static_cast(sc.ch); + if (setBashOperator.Contains(sc.chNext)) { + s[1] = static_cast(sc.chNext); + s[2] = '\0'; + isCmdDelim = cmdDelimiter.InList(s); + if (isCmdDelim) + sc.Forward(); + } + if (!isCmdDelim) { + s[1] = '\0'; + isCmdDelim = cmdDelimiter.InList(s); + } + if (isCmdDelim) { + cmdState = CmdState::Delimiter; + sc.Forward(); + continue; + } + } + // handle closing delimiters for test/arithmetic expressions - )),]],] + if (cmdState == CmdState::Arithmetic && sc.Match(')', ')')) { + cmdState = CmdState::Body; + sc.Forward(); + } else if (sc.ch == ']' && IsASpace(sc.chPrev)) { + if (cmdState == CmdState::SingleBracket) { + cmdState = CmdState::Body; + } else if (cmdState == CmdState::DoubleBracket && sc.chNext == ']') { + cmdState = CmdState::Body; + sc.Forward(); + } + } + } + }// sc.state + + sc.Forward(); + } + sc.Complete(); + if (MaskCommand(sc.state) == SCE_SH_HERE_Q) { + styler.ChangeLexerState(sc.currentPos, styler.Length()); + } + sc.Complete(); +} + +void SCI_METHOD LexerBash::Fold(Sci_PositionU startPos_, Sci_Position length, int initStyle, IDocument *pAccess) { + if(!options.fold) + return; + + LexAccessor styler(pAccess); + + Sci_Position startPos = startPos_; + const Sci_Position endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + // Backtrack to previous line in case need to fix its fold status + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + initStyle = (startPos > 0) ? styler.StyleIndexAt(startPos - 1) : 0; + } + + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = MaskCommand(styler.StyleIndexAt(startPos)); + int style = MaskCommand(initStyle); + char word[8] = { '\0' }; // we're not interested in long words anyway + size_t wordlen = 0; + for (Sci_Position i = startPos; i < endPos; i++) { + const char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + const int stylePrev = style; + style = styleNext; + styleNext = MaskCommand(styler.StyleIndexAt(i + 1)); + const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + // Comment folding + if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent + 1, styler)) + levelCurrent--; + } + + switch (style) { + case SCE_SH_WORD: + if ((wordlen + 1) < sizeof(word)) + word[wordlen++] = ch; + if (styleNext != style) { + word[wordlen] = '\0'; + wordlen = 0; + if (InList(word, {"if", "case", "do"})) { + levelCurrent++; + } else if (InList(word, {"fi", "esac", "done"})) { + levelCurrent--; + } + } + break; + + case SCE_SH_OPERATOR: + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + break; + + // Here Document folding + case SCE_SH_HERE_DELIM: + if (stylePrev == SCE_SH_HERE_Q) { + levelCurrent--; + } else if (stylePrev != SCE_SH_HERE_DELIM) { + if (ch == '<' && chNext == '<') { + if (styler.SafeGetCharAt(i + 2) != '<') { + levelCurrent++; + } + } + } + break; + case SCE_SH_HERE_Q: + if (styleNext == SCE_SH_DEFAULT) { + levelCurrent--; + } + break; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + const int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +extern const LexerModule lmBash(SCLEX_BASH, LexerBash::LexerFactoryBash, "bash", bashWordListDesc); diff --git a/src/lexilla/lexers/LexBasic.cxx b/src/lexilla/lexers/LexBasic.cxx new file mode 100644 index 000000000..3c41eb443 --- /dev/null +++ b/src/lexilla/lexers/LexBasic.cxx @@ -0,0 +1,573 @@ +// Scintilla source code edit control +/** @file LexBasic.cxx + ** Lexer for BlitzBasic and PureBasic. + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics +// and derivatives. Once they diverge enough, might want to split it into multiple +// lexers for more code clearity. +// +// Mail me (elias users sf net) for any bugs. + +// Folding only works for simple things like functions or types. + +// You may want to have a look at my ctags lexer as well, if you additionally to coloring +// and folding need to extract things like label tags in your editor. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + * 64 - letter + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 84, 84, 84, 84, 84, 84, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 2, 2, 2, 68, + 2, 84, 84, 84, 84, 84, 84, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsOperator(int c) { + return c < 128 && (character_classification[c] & 2); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static bool IsDigit(int c) { + return c < 128 && (character_classification[c] & 8); +} + +static bool IsHexDigit(int c) { + return c < 128 && (character_classification[c] & 16); +} + +static bool IsBinDigit(int c) { + return c < 128 && (character_classification[c] & 32); +} + +static bool IsLetter(int c) { + return c < 128 && (character_classification[c] & 64); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int CheckBlitzFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "type")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end type")) { + return -1; + } + return 0; +} + +static int CheckPureFoldPoint(char const *token, int &level) { + if (!strcmp(token, "procedure") || + !strcmp(token, "enumeration") || + !strcmp(token, "interface") || + !strcmp(token, "structure")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "endprocedure") || + !strcmp(token, "endenumeration") || + !strcmp(token, "endinterface") || + !strcmp(token, "endstructure")) { + return -1; + } + return 0; +} + +static int CheckFreeFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "sub") || + !strcmp(token, "enum") || + !strcmp(token, "type") || + !strcmp(token, "union") || + !strcmp(token, "property") || + !strcmp(token, "destructor") || + !strcmp(token, "constructor")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end sub") || + !strcmp(token, "end enum") || + !strcmp(token, "end type") || + !strcmp(token, "end union") || + !strcmp(token, "end property") || + !strcmp(token, "end destructor") || + !strcmp(token, "end constructor")) { + return -1; + } + return 0; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerBasic +struct OptionsBasic { + bool fold; + bool foldSyntaxBased; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + OptionsBasic() { + fold = false; + foldSyntaxBased = true; + foldCommentExplicit = false; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + } +}; + +static const char * const blitzbasicWordListDesc[] = { + "BlitzBasic Keywords", + "user1", + "user2", + "user3", + 0 +}; + +static const char * const purebasicWordListDesc[] = { + "PureBasic Keywords", + "PureBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +static const char * const freebasicWordListDesc[] = { + "FreeBasic Keywords", + "FreeBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +struct OptionSetBasic : public OptionSet { + OptionSetBasic(const char * const wordListDescriptions[]) { + DefineProperty("fold", &OptionsBasic::fold); + + DefineProperty("fold.basic.syntax.based", &OptionsBasic::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.basic.comment.explicit", &OptionsBasic::foldCommentExplicit, + "This option enables folding explicit fold points when using the Basic lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ (BB/PB) or '{ (FB) comment at the start " + "and a ;} (BB/PB) or '} (FB) at the end of a section that should be folded."); + + DefineProperty("fold.basic.explicit.start", &OptionsBasic::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard ;{ (BB/PB) or '{ (FB)."); + + DefineProperty("fold.basic.explicit.end", &OptionsBasic::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard ;} (BB/PB) or '} (FB)."); + + DefineProperty("fold.basic.explicit.anywhere", &OptionsBasic::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsBasic::foldCompact); + + DefineWordListSets(wordListDescriptions); + } +}; + +class LexerBasic : public DefaultLexer { + char comment_char; + int (*CheckFoldPoint)(char const *, int &); + WordList keywordlists[4]; + OptionsBasic options; + OptionSetBasic osBasic; +public: + LexerBasic(const char *languageName_, int language_, char comment_char_, + int (*CheckFoldPoint_)(char const *, int &), const char * const wordListDescriptions[]) : + DefaultLexer(languageName_, language_), + comment_char(comment_char_), + CheckFoldPoint(CheckFoldPoint_), + osBasic(wordListDescriptions) { + } + virtual ~LexerBasic() { + } + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char * SCI_METHOD PropertyNames() override { + return osBasic.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osBasic.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osBasic.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char *key) override { + return osBasic.PropertyGet(key); + } + const char * SCI_METHOD DescribeWordListSets() override { + return osBasic.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + static ILexer5 *LexerFactoryBlitzBasic() { + return new LexerBasic("blitzbasic", SCLEX_BLITZBASIC, ';', CheckBlitzFoldPoint, blitzbasicWordListDesc); + } + static ILexer5 *LexerFactoryPureBasic() { + return new LexerBasic("purebasic", SCLEX_PUREBASIC, ';', CheckPureFoldPoint, purebasicWordListDesc); + } + static ILexer5 *LexerFactoryFreeBasic() { + return new LexerBasic("freebasic", SCLEX_FREEBASIC, '\'', CheckFreeFoldPoint, freebasicWordListDesc ); + } +}; + +Sci_Position SCI_METHOD LexerBasic::PropertySet(const char *key, const char *val) { + if (osBasic.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerBasic::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywordlists[0]; + break; + case 1: + wordListN = &keywordlists[1]; + break; + case 2: + wordListN = &keywordlists[2]; + break; + case 3: + wordListN = &keywordlists[3]; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerBasic::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + bool wasfirst = true, isfirst = true; // true if first token in a line + styler.StartAt(startPos); + int styleBeforeKeyword = SCE_B_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + // Can't use sc.More() here else we miss the last character + for (; ; sc.Forward()) { + if (sc.state == SCE_B_IDENTIFIER) { + if (!IsIdentifier(sc.ch)) { + // Labels + if (wasfirst && sc.Match(':')) { + sc.ChangeState(SCE_B_LABEL); + sc.ForwardSetState(SCE_B_DEFAULT); + } else { + char s[100]; + int kstates[4] = { + SCE_B_KEYWORD, + SCE_B_KEYWORD2, + SCE_B_KEYWORD3, + SCE_B_KEYWORD4, + }; + sc.GetCurrentLowered(s, sizeof(s)); + for (int i = 0; i < 4; i++) { + if (keywordlists[i].InList(s)) { + sc.ChangeState(kstates[i]); + } + } + // Types, must set them as operator else they will be + // matched as number/constant + if (sc.Match('.') || sc.Match('$') || sc.Match('%') || + sc.Match('#')) { + sc.SetState(SCE_B_OPERATOR); + } else { + sc.SetState(SCE_B_DEFAULT); + } + } + } + } else if (sc.state == SCE_B_OPERATOR) { + if (!IsOperator(sc.ch) || sc.Match('#')) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_LABEL) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_CONSTANT) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_NUMBER) { + if (!IsDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_HEXNUMBER) { + if (!IsHexDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_BINNUMBER) { + if (!IsBinDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_STRING) { + if (sc.ch == '"') { + sc.ForwardSetState(SCE_B_DEFAULT); + } + if (sc.atLineEnd) { + sc.ChangeState(SCE_B_ERROR); + sc.SetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_COMMENT || sc.state == SCE_B_PREPROCESSOR) { + if (sc.atLineEnd) { + sc.SetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_DOCLINE) { + if (sc.atLineEnd) { + sc.SetState(SCE_B_DEFAULT); + } else if (sc.ch == '\\' || sc.ch == '@') { + if (IsLetter(sc.chNext) && sc.chPrev != '\\') { + styleBeforeKeyword = sc.state; + sc.SetState(SCE_B_DOCKEYWORD); + }; + } + } else if (sc.state == SCE_B_DOCKEYWORD) { + if (IsSpace(sc.ch)) { + sc.SetState(styleBeforeKeyword); + } else if (sc.atLineEnd && styleBeforeKeyword == SCE_B_DOCLINE) { + sc.SetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_COMMENTBLOCK) { + if (sc.Match("\'/")) { + sc.Forward(); + sc.ForwardSetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_DOCBLOCK) { + if (sc.Match("\'/")) { + sc.Forward(); + sc.ForwardSetState(SCE_B_DEFAULT); + } else if (sc.ch == '\\' || sc.ch == '@') { + if (IsLetter(sc.chNext) && sc.chPrev != '\\') { + styleBeforeKeyword = sc.state; + sc.SetState(SCE_B_DOCKEYWORD); + }; + } + } + + if (sc.atLineStart) + isfirst = true; + + if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) { + if (isfirst && sc.Match('.') && comment_char != '\'') { + sc.SetState(SCE_B_LABEL); + } else if (isfirst && sc.Match('#')) { + wasfirst = isfirst; + sc.SetState(SCE_B_IDENTIFIER); + } else if (sc.Match(comment_char)) { + // Hack to make deprecated QBASIC '$Include show + // up in freebasic with SCE_B_PREPROCESSOR. + if (comment_char == '\'' && sc.Match(comment_char, '$')) + sc.SetState(SCE_B_PREPROCESSOR); + else if (sc.Match("\'*") || sc.Match("\'!")) { + sc.SetState(SCE_B_DOCLINE); + } else { + sc.SetState(SCE_B_COMMENT); + } + } else if (sc.Match("/\'")) { + if (sc.Match("/\'*") || sc.Match("/\'!")) { // Support of gtk-doc/Doxygen doc. style + sc.SetState(SCE_B_DOCBLOCK); + } else { + sc.SetState(SCE_B_COMMENTBLOCK); + } + sc.Forward(); // Eat the ' so it isn't used for the end of the comment + } else if (sc.Match('"')) { + sc.SetState(SCE_B_STRING); + } else if (IsDigit(sc.ch)) { + sc.SetState(SCE_B_NUMBER); + } else if (sc.Match('$') || sc.Match("&h") || sc.Match("&H") || sc.Match("&o") || sc.Match("&O")) { + sc.SetState(SCE_B_HEXNUMBER); + } else if (sc.Match('%') || sc.Match("&b") || sc.Match("&B")) { + sc.SetState(SCE_B_BINNUMBER); + } else if (sc.Match('#')) { + sc.SetState(SCE_B_CONSTANT); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_B_OPERATOR); + } else if (IsIdentifier(sc.ch)) { + wasfirst = isfirst; + sc.SetState(SCE_B_IDENTIFIER); + } else if (!IsSpace(sc.ch)) { + sc.SetState(SCE_B_ERROR); + } + } + + if (!IsSpace(sc.ch)) + isfirst = false; + + if (!sc.More()) + break; + } + sc.Complete(); +} + + +void SCI_METHOD LexerBasic::Fold(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + Sci_Position line = styler.GetLine(startPos); + int level = styler.LevelAt(line); + int go = 0, done = 0; + Sci_Position endPos = startPos + length; + char word[256]; + int wordlen = 0; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + int cNext = styler[startPos]; + + // Scan for tokens at the start of the line (they may include + // whitespace, for tokens like "End Function" + for (Sci_Position i = startPos; i < endPos; i++) { + int c = cNext; + cNext = styler.SafeGetCharAt(i + 1); + bool atEOL = (c == '\r' && cNext != '\n') || (c == '\n'); + if (options.foldSyntaxBased && !done && !go) { + if (wordlen) { // are we scanning a token already? + word[wordlen] = static_cast(LowerCase(c)); + if (!IsIdentifier(c)) { // done with token + word[wordlen] = '\0'; + go = CheckFoldPoint(word, level); + if (!go) { + // Treat any whitespace as single blank, for + // things like "End Function". + if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { + word[wordlen] = ' '; + if (wordlen < 255) + wordlen++; + } + else // done with this line + done = 1; + } + } else if (wordlen < 255) { + wordlen++; + } + } else { // start scanning at first non-whitespace character + if (!IsSpace(c)) { + if (IsIdentifier(c)) { + word[0] = static_cast(LowerCase(c)); + wordlen = 1; + } else // done with this line + done = 1; + } + } + } + if (options.foldCommentExplicit && ((styler.StyleAt(i) == SCE_B_COMMENT) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + level |= SC_FOLDLEVELHEADERFLAG; + go = 1; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + go = -1; + } + } else { + if (c == comment_char) { + if (cNext == '{') { + level |= SC_FOLDLEVELHEADERFLAG; + go = 1; + } else if (cNext == '}') { + go = -1; + } + } + } + } + if (atEOL) { // line end + if (!done && wordlen == 0 && options.foldCompact) // line was only space + level |= SC_FOLDLEVELWHITEFLAG; + if (level != styler.LevelAt(line)) + styler.SetLevel(line, level); + level += go; + line++; + // reset state + wordlen = 0; + level &= ~SC_FOLDLEVELHEADERFLAG; + level &= ~SC_FOLDLEVELWHITEFLAG; + go = 0; + done = 0; + } + } +} + +extern const LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, LexerBasic::LexerFactoryBlitzBasic, "blitzbasic", blitzbasicWordListDesc); + +extern const LexerModule lmPureBasic(SCLEX_PUREBASIC, LexerBasic::LexerFactoryPureBasic, "purebasic", purebasicWordListDesc); + +extern const LexerModule lmFreeBasic(SCLEX_FREEBASIC, LexerBasic::LexerFactoryFreeBasic, "freebasic", freebasicWordListDesc); diff --git a/src/lexilla/lexers/LexBatch.cxx b/src/lexilla/lexers/LexBatch.cxx new file mode 100644 index 000000000..d295965de --- /dev/null +++ b/src/lexilla/lexers/LexBatch.cxx @@ -0,0 +1,646 @@ +// Scintilla source code edit control +/** @file LexBatch.cxx + ** Lexer for batch files. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "InList.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +namespace { + +constexpr bool Is0To9(char ch) noexcept { + return (ch >= '0') && (ch <= '9'); +} + +bool IsAlphabetic(int ch) noexcept { + return IsASCII(ch) && isalpha(ch); +} + +inline bool AtEOL(Accessor &styler, Sci_PositionU i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +// Tests for BATCH Operators +constexpr bool IsBOperator(char ch) noexcept { + return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || + (ch == '|') || (ch == '?') || (ch == '*')|| + (ch == '&') || (ch == '(') || (ch == ')'); +} + +// Tests for BATCH Separators +constexpr bool IsBSeparator(char ch) noexcept { + return (ch == '\\') || (ch == '.') || (ch == ';') || + (ch == '\"') || (ch == '\'') || (ch == '/'); +} + +// Tests for escape character +constexpr bool IsEscaped(const char* wordStr, Sci_PositionU pos) noexcept { + bool isQoted=false; + while (pos>0){ + pos--; + if (wordStr[pos]=='^') + isQoted=!isQoted; + else + break; + } + return isQoted; +} + +constexpr bool IsQuotedBy(std::string_view svBuffer, char quote) noexcept { + bool CurrentStatus = false; + size_t pQuote = svBuffer.find(quote); + while (pQuote != std::string_view::npos) { + if (!IsEscaped(svBuffer.data(), pQuote)) { + CurrentStatus = !CurrentStatus; + } + pQuote = svBuffer.find(quote, pQuote + 1); + } + return CurrentStatus; +} + +// Tests for quote character +constexpr bool textQuoted(const char *lineBuffer, Sci_PositionU endPos) noexcept { + const std::string_view svBuffer(lineBuffer, endPos); + return IsQuotedBy(svBuffer, '\"') || IsQuotedBy(svBuffer, '\''); +} + +void ColouriseBatchDoc( + Sci_PositionU startPos, + Sci_Position length, + int /*initStyle*/, + WordList *keywordlists[], + Accessor &styler) { + // Always backtracks to the start of a line that is not a continuation + // of the previous line + if (startPos > 0) { + Sci_Position ln = styler.GetLine(startPos); // Current line number + while (startPos > 0) { + ln--; + if ((styler.SafeGetCharAt(startPos-3) == '^' && styler.SafeGetCharAt(startPos-2) == '\r' && styler.SafeGetCharAt(startPos-1) == '\n') + || styler.SafeGetCharAt(startPos-2) == '^') { // handle '^' line continuation + // When the line continuation is found, + // set the Start Position to the Start of the previous line + length+=startPos-styler.LineStart(ln); + startPos=styler.LineStart(ln); + } + else + break; + } + } + + char lineBuffer[1024] {}; + + styler.StartAt(startPos); + styler.StartSegment(startPos); + Sci_PositionU linePos = 0; + Sci_PositionU startLine = startPos; + bool continueProcessing = true; // Used to toggle Regular Keyword Checking + bool isNotAssigned=false; // Used to flag Assignment in Set operation + + for (Sci_PositionU i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1) || (i==startPos + length-1)) { + // End of line (or of line buffer) (or End of Last Line) met, colourise it + lineBuffer[linePos] = '\0'; + const Sci_PositionU lengthLine=linePos; + const Sci_PositionU endPos=i; + const WordList &keywords = *keywordlists[0]; // Internal Commands + const WordList &keywords2 = *keywordlists[1]; // External Commands (optional) + + // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords + // Toggling Regular Keyword Checking off improves readability + // Other Regular Keywords and External Commands / Programs might also benefit from toggling + // Need a more robust algorithm to properly toggle Regular Keyword Checking + bool stopLineProcessing=false; // Used to stop line processing if Comment or Drive Change found + + Sci_PositionU offset = 0; // Line Buffer Offset + // Skip initial spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + // Set External Command / Program Location + Sci_PositionU cmdLoc = offset; + + // Check for Fake Label (Comment) or Real Label - return if found + if (lineBuffer[offset] == ':') { + if (lineBuffer[offset + 1] == ':') { + // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm + styler.ColourTo(endPos, SCE_BAT_COMMENT); + } else { + // Colorize Real Label + // :[\t ]*[^\t &+:<>|]+ + const char *startLabelName = lineBuffer + offset + 1; + const size_t whitespaceLength = strspn(startLabelName, "\t "); + // Set of label-terminating characters determined experimentally + const char *endLabel = strpbrk(startLabelName + whitespaceLength, "\t &+:<>|"); + if (endLabel) { + styler.ColourTo(startLine + offset + endLabel - startLabelName, SCE_BAT_LABEL); + styler.ColourTo(endPos, SCE_BAT_AFTER_LABEL); // New style + } else { + styler.ColourTo(endPos, SCE_BAT_LABEL); + } + } + stopLineProcessing=true; + // Check for Drive Change (Drive Change is internal command) - return if found + } else if ((IsAlphabetic(lineBuffer[offset])) && + (lineBuffer[offset + 1] == ':') && + ((isspacechar(lineBuffer[offset + 2])) || + (((lineBuffer[offset + 2] == '\\')) && + (isspacechar(lineBuffer[offset + 3]))))) { + // Colorize Regular Keyword + styler.ColourTo(endPos, SCE_BAT_WORD); + stopLineProcessing=true; + } + + // Check for Hide Command (@ECHO OFF/ON) + if (lineBuffer[offset] == '@') { + styler.ColourTo(startLine + offset, SCE_BAT_HIDE); + offset++; + } + // Skip next spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + + // Read remainder of line word-at-a-time or remainder-of-word-at-a-time + while (offset < lengthLine && !stopLineProcessing) { + if (offset > startLine) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + char wordBuffer[81]{}; // Word Buffer - large to catch long paths + // Copy word from Line Buffer into Word Buffer and convert to lower case + Sci_PositionU wbl = 0; // Word Buffer Length + for (; offset < lengthLine && wbl < 80 && + !isspacechar(lineBuffer[offset]); wbl++, offset++) { + wordBuffer[wbl] = MakeLowerCase(lineBuffer[offset]); + } + wordBuffer[wbl] = '\0'; + const std::string_view wordView(wordBuffer); + Sci_PositionU wbo = 0; // Word Buffer Offset - also Special Keyword Buffer Length + + // Check for Comment - return if found + if (continueProcessing) { + if ((wordView == "rem") || (wordBuffer[0] == ':' && wordBuffer[1] == ':')) { + if ((offset == wbl) || !textQuoted(lineBuffer, offset - wbl)) { + styler.ColourTo(startLine + offset - wbl - 1, SCE_BAT_DEFAULT); + styler.ColourTo(endPos, SCE_BAT_COMMENT); + break; + } + } + } + // Check for Separator + if (IsBSeparator(wordBuffer[0])) { + // Check for External Command / Program + if ((cmdLoc == offset - wbl) && + ((wordBuffer[0] == ':') || + (wordBuffer[0] == '\\') || + (wordBuffer[0] == '.'))) { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Reset External Command / Program Location + cmdLoc = offset; + } else { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Check for Regular Keyword in list + } else if ((keywords.InList(wordBuffer)) && + (continueProcessing)) { + // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking + if (InList(wordView, {"echo", "goto", "prompt"})) { + continueProcessing = false; + } + // SET requires additional processing for the assignment operator + if (wordView == "set") { + continueProcessing = false; + isNotAssigned=true; + } + // Identify External Command / Program Location for ERRORLEVEL, and EXIST + if (InList(wordView, {"errorlevel", "exist"})) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip comparison + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH + } else if (InList(wordView, {"call", "do", "loadhigh", "lh"})) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Check if call is followed by a label + if ((lineBuffer[cmdLoc] == ':') && + (wordView == "call")) { + continueProcessing = false; + } + } + // Colorize Regular keyword + styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); + // No need to Reset Offset + // Check for Special Keyword in list, External Command / Program, or Default Text + } else if ((wordBuffer[0] != '%') && + (wordBuffer[0] != '!') && + (!IsBOperator(wordBuffer[0])) && + (continueProcessing)) { + // Check for Special Keyword + // Affected Commands are in Length range 2-6 + // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected + bool sKeywordFound = false; // Exit Special Keyword for-loop if found + for (Sci_PositionU keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { + // Special Keywords are those that allow certain characters without whitespace after the command + // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= + // Special Keyword Buffer used to determine if the first n characters is a Keyword + char sKeywordBuffer[10]{}; // Special Keyword Buffer + wbo = 0; + // Copy Keyword Length from Word Buffer into Special Keyword Buffer + for (; wbo < keywordLength; wbo++) { + sKeywordBuffer[wbo] = wordBuffer[wbo]; + } + sKeywordBuffer[wbo] = '\0'; + // Check for Special Keyword in list + if ((keywords.InList(sKeywordBuffer)) && + ((IsBOperator(wordBuffer[wbo])) || + (IsBSeparator(wordBuffer[wbo])) || + (wordBuffer[wbo] == ':' && + (InList(sKeywordBuffer, {"call", "echo", "goto"}) )))) { + sKeywordFound = true; + // ECHO requires no further Regular Keyword Checking + if (std::string_view(sKeywordBuffer) == "echo") { + continueProcessing = false; + } + // Colorize Special Keyword as Regular Keyword + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for External Command / Program or Default Text + if (!sKeywordFound) { + wbo = 0; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (((wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))))) { + wbo++; + } + // Reset External Command / Program Location + cmdLoc = offset - (wbl - wbo); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // CHOICE requires no further Regular Keyword Checking + if (wordView == "choice") { + continueProcessing = false; + } + // Check for START (and its switches) - What follows is External Command \ Program + if (wordView == "start") { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Reset External Command / Program Location if command switch detected + if (lineBuffer[cmdLoc] == '/') { + // Skip command switch + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + } + } + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // No need to Reset Offset + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (((wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) + } else if (wordBuffer[0] == '%') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second % (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '%')) { + wbo++; + } + // Check for Argument (%n) or (%*) + if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && + (wordBuffer[wbo] != '%')) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 2); + } + // Colorize Argument + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Expanded Argument (%~...) / Variable (%%~...) + // Expanded Argument: %~[] + // Expanded Variable: %%~[] + // Path operators are exclusively alphabetic. + // Expanded arguments have a single digit at the end. + // Expanded variables have a single identifier character as variable name. + } else if (((wbl > 1) && (wordBuffer[1] == '~')) || + ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + const bool isArgument = (wordBuffer[1] == '~'); + if (isArgument) { + Sci_PositionU expansionStopOffset = 2; + bool isValid = false; + for (; expansionStopOffset < wbl; expansionStopOffset++) { + if (Is0To9(wordBuffer[expansionStopOffset])) { + expansionStopOffset++; + isValid = true; + wbo = expansionStopOffset; + // Colorize Expanded Argument + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + break; + } + } + if (!isValid) { + // not a valid expanded argument or variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + } + // Expanded Variable + } else { + // start after ~ + wbo = 3; + // Search to end of word for another % (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + if (wbo > 3) { + // Colorize Expanded Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + } else { + // not a valid expanded argument or variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + } + } + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Environment Variable (%x...%) + } else if ((wordBuffer[1] != '%') && + (wordBuffer[wbo] == '%')) { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Local Variable (%%a) + } else if ( + (wbl > 2) && + (wordBuffer[1] == '%') && + (wordBuffer[2] != '%') && + (!IsBOperator(wordBuffer[2])) && + (!IsBSeparator(wordBuffer[2]))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 3); + } + // Colorize Local Variable + styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 3); + // escaped % + } else if ( + (wbl > 1) && + (wordBuffer[1] == '%')) { + + // Reset Offset to re-process remainder of word + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_DEFAULT); + offset -= (wbl - 2); + } + // Check for Environment Variable (!x...!) + } else if (wordBuffer[0] == '!') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second ! (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '!')) { + wbo++; + } + if (wordBuffer[wbo] == '!') { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + // Check for Operator + } else if (IsBOperator(wordBuffer[0])) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + // Check for Comparison Operator + if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { + // Identify External Command / Program Location for IF + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Comparison Operator + if (continueProcessing) + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); + else + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Pipe Operator + } else if ((wordBuffer[0] == '|') && + !(IsEscaped(lineBuffer,offset - wbl + wbo) || textQuoted(lineBuffer, offset - wbl) )) { + // Reset External Command / Program Location + cmdLoc = offset - wbl + 1; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Pipe Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + continueProcessing = true; + // Check for Other Operator + } else { + // Check for Operators: >, |, & + if (((wordBuffer[0] == '>')|| + (wordBuffer[0] == ')')|| + (wordBuffer[0] == '(')|| + (wordBuffer[0] == '&' )) && + !(!continueProcessing && (IsEscaped(lineBuffer,offset - wbl + wbo) + || textQuoted(lineBuffer, offset - wbl) ))){ + // Turn Keyword and External Command / Program checking back on + continueProcessing = true; + isNotAssigned=false; + } + // Colorize Other Operators + // Do not Colorize Parenthesis, quoted text and escaped operators + if (((wordBuffer[0] != ')') && (wordBuffer[0] != '(') + && !textQuoted(lineBuffer, offset - wbl) && !IsEscaped(lineBuffer,offset - wbl + wbo)) + && !((wordBuffer[0] == '=') && !isNotAssigned )) + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + else + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + + if ((wordBuffer[0] == '=') && isNotAssigned ){ + isNotAssigned=false; + } + } + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + ((wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo])))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + // Skip next spaces - nothing happens if Offset was Reset + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + } + // Colorize Default Text for remainder of line - currently not lexed + styler.ColourTo(endPos, SCE_BAT_DEFAULT); + + // handle line continuation for SET and ECHO commands except the last line + if (!continueProcessing && (i2) && lineBuffer[linePos-2]=='\r') // Windows EOL + lineContinuationPos=linePos-3; + else + lineContinuationPos=linePos-2; // Unix or Mac EOL + // Reset continueProcessing if line continuation was not found + if ((lineBuffer[lineContinuationPos]!='^') + || IsEscaped(lineBuffer, lineContinuationPos) + || textQuoted(lineBuffer, lineContinuationPos)) + continueProcessing=true; + } + } + + linePos = 0; + startLine = i + 1; + } + } +} + +const char *const batchWordListDesc[] = { + "Internal Commands", + "External Commands", + nullptr +}; + +} + +extern const LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", nullptr, batchWordListDesc); diff --git a/src/lexilla/lexers/LexBibTeX.cxx b/src/lexilla/lexers/LexBibTeX.cxx new file mode 100644 index 000000000..7a0aa28f4 --- /dev/null +++ b/src/lexilla/lexers/LexBibTeX.cxx @@ -0,0 +1,309 @@ +// Copyright 2008-2010 Sergiu Dotenco. The License.txt file describes the +// conditions under which this software may be distributed. + +/** + * @file LexBibTeX.cxx + * @brief General BibTeX coloring scheme. + * @author Sergiu Dotenco + * @date April 18, 2009 + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +namespace { + bool IsAlphabetic(unsigned int ch) + { + return IsASCII(ch) && std::isalpha(ch) != 0; + } + bool IsAlphaNumeric(char ch) + { + return IsASCII(ch) && std::isalnum(ch); + } + + bool EqualCaseInsensitive(const char* a, const char* b) + { + return CompareCaseInsensitive(a, b) == 0; + } + + bool EntryWithoutKey(const char* name) + { + return EqualCaseInsensitive(name,"string"); + } + + char GetClosingBrace(char openbrace) + { + char result = openbrace; + + switch (openbrace) { + case '(': result = ')'; break; + case '{': result = '}'; break; + } + + return result; + } + + bool IsEntryStart(char prev, char ch) + { + return prev != '\\' && ch == '@'; + } + + bool IsEntryStart(const StyleContext& sc) + { + return IsEntryStart(sc.chPrev, sc.ch); + } + + void ColorizeBibTeX(Sci_PositionU start_pos, Sci_Position length, int /*init_style*/, WordList* keywordlists[], Accessor& styler) + { + WordList &EntryNames = *keywordlists[0]; + bool fold_compact = styler.GetPropertyInt("fold.compact", 1) != 0; + + std::string buffer; + buffer.reserve(25); + + // We always colorize a section from the beginning, so let's + // search for the @ character which isn't escaped, i.e. \@ + while (start_pos > 0 && !IsEntryStart(styler.SafeGetCharAt(start_pos - 1), + styler.SafeGetCharAt(start_pos))) { + --start_pos; ++length; + } + + styler.StartAt(start_pos); + styler.StartSegment(start_pos); + + Sci_Position current_line = styler.GetLine(start_pos); + int prev_level = styler.LevelAt(current_line) & SC_FOLDLEVELNUMBERMASK; + int current_level = prev_level; + int visible_chars = 0; + + bool in_comment = false ; + StyleContext sc(start_pos, length, SCE_BIBTEX_DEFAULT, styler); + + bool going = sc.More(); // needed because of a fuzzy end of file state + char closing_brace = 0; + bool collect_entry_name = false; + + for (; going; sc.Forward()) { + if (!sc.More()) + going = false; // we need to go one behind the end of text + + if (in_comment) { + if (sc.atLineEnd) { + sc.SetState(SCE_BIBTEX_DEFAULT); + in_comment = false; + } + } + else { + // Found @entry + if (IsEntryStart(sc)) { + sc.SetState(SCE_BIBTEX_UNKNOWN_ENTRY); + sc.Forward(); + ++current_level; + + buffer.clear(); + collect_entry_name = true; + } + else if ((sc.state == SCE_BIBTEX_ENTRY || sc.state == SCE_BIBTEX_UNKNOWN_ENTRY) + && (sc.ch == '{' || sc.ch == '(')) { + // Entry name colorization done + // Found either a { or a ( after entry's name, e.g. @entry(...) @entry{...} + // Closing counterpart needs to be stored. + closing_brace = GetClosingBrace(sc.ch); + + sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize { ( + + // @string doesn't have any key + if (EntryWithoutKey(buffer.c_str())) + sc.ForwardSetState(SCE_BIBTEX_PARAMETER); + else + sc.ForwardSetState(SCE_BIBTEX_KEY); // Key/label colorization + } + + // Need to handle the case where entry's key is empty + // e.g. @book{,...} + if (sc.state == SCE_BIBTEX_KEY && sc.ch == ',') { + // Key/label colorization done + sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the , + sc.ForwardSetState(SCE_BIBTEX_PARAMETER); // Parameter colorization + } + else if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == '=') { + sc.SetState(SCE_BIBTEX_DEFAULT); // Don't colorize the = + sc.ForwardSetState(SCE_BIBTEX_VALUE); // Parameter value colorization + + Sci_Position start = sc.currentPos; + + // We need to handle multiple situations: + // 1. name"one two {three}" + // 2. name={one {one two {two}} three} + // 3. year=2005 + + // Skip ", { until we encounter the first alphanumerical character + while (sc.More() && !(IsAlphaNumeric(sc.ch) || sc.ch == '"' || sc.ch == '{')) + sc.Forward(); + + if (sc.More()) { + // Store " or { + char ch = sc.ch; + + // Not interested in alphanumerical characters + if (IsAlphaNumeric(ch)) + ch = 0; + + int skipped = 0; + + if (ch) { + // Skip preceding " or { such as in name={{test}}. + // Remember how many characters have been skipped + // Make sure that empty values, i.e. "" are also handled correctly + while (sc.More() && (sc.ch == ch && (ch != '"' || skipped < 1))) { + sc.Forward(); + ++skipped; + } + } + + // Closing counterpart for " is the same character + if (ch == '{') + ch = '}'; + + // We have reached the parameter value + // In case the open character was a alnum char, skip until , is found + // otherwise until skipped == 0 + while (sc.More() && (skipped > 0 || (!ch && !(sc.ch == ',' || sc.ch == closing_brace)))) { + // Make sure the character isn't escaped + if (sc.chPrev != '\\') { + // Parameter value contains a { which is the 2nd case described above + if (sc.ch == '{') + ++skipped; // Remember it + else if (sc.ch == '}') + --skipped; + else if (skipped == 1 && sc.ch == ch && ch == '"') // Don't ignore cases like {"o} + skipped = 0; + } + + sc.Forward(); + } + } + + // Don't colorize the , + sc.SetState(SCE_BIBTEX_DEFAULT); + + // Skip until the , or entry's closing closing_brace is found + // since this parameter might be the last one + while (sc.More() && !(sc.ch == ',' || sc.ch == closing_brace)) + sc.Forward(); + + int state = SCE_BIBTEX_PARAMETER; // The might be more parameters + + // We've reached the closing closing_brace for the bib entry + // in case no " or {} has been used to enclose the value, + // as in 3rd case described above + if (sc.ch == closing_brace) { + --current_level; + // Make sure the text between entries is not colored + // using parameter's style + state = SCE_BIBTEX_DEFAULT; + } + + Sci_Position end = sc.currentPos; + current_line = styler.GetLine(end); + + // We have possibly skipped some lines, so the folding levels + // have to be adjusted separately + for (Sci_Position i = styler.GetLine(start); i <= styler.GetLine(end); ++i) + styler.SetLevel(i, prev_level); + + sc.ForwardSetState(state); + } + + if (sc.state == SCE_BIBTEX_PARAMETER && sc.ch == closing_brace) { + sc.SetState(SCE_BIBTEX_DEFAULT); + --current_level; + } + + // Non escaped % found which represents a comment until the end of the line + if (sc.chPrev != '\\' && sc.ch == '%') { + in_comment = true; + sc.SetState(SCE_BIBTEX_COMMENT); + } + } + + if (sc.state == SCE_BIBTEX_UNKNOWN_ENTRY || sc.state == SCE_BIBTEX_ENTRY) { + if (!IsAlphabetic(sc.ch) && collect_entry_name) + collect_entry_name = false; + + if (collect_entry_name) { + buffer += static_cast(tolower(sc.ch)); + if (EntryNames.InList(buffer.c_str())) + sc.ChangeState(SCE_BIBTEX_ENTRY); + else + sc.ChangeState(SCE_BIBTEX_UNKNOWN_ENTRY); + } + } + + if (sc.atLineEnd) { + int level = prev_level; + + if (visible_chars == 0 && fold_compact) + level |= SC_FOLDLEVELWHITEFLAG; + + if ((current_level > prev_level)) + level |= SC_FOLDLEVELHEADERFLAG; + // else if (current_level < prev_level) + // level |= SC_FOLDLEVELBOXFOOTERFLAG; // Deprecated + + if (level != styler.LevelAt(current_line)) { + styler.SetLevel(current_line, level); + } + + ++current_line; + prev_level = current_level; + visible_chars = 0; + } + + if (!isspacechar(sc.ch)) + ++visible_chars; + } + + sc.Complete(); + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(current_line) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(current_line, prev_level | flagsNext); + } +} +static const char * const BibTeXWordLists[] = { + "Entry Names", + 0, +}; + + +extern const LexerModule lmBibTeX(SCLEX_BIBTEX, ColorizeBibTeX, "bib", 0, BibTeXWordLists); + +// Entry Names +// article, book, booklet, conference, inbook, +// incollection, inproceedings, manual, mastersthesis, +// misc, phdthesis, proceedings, techreport, unpublished, +// string, url + diff --git a/src/lexilla/lexers/LexBullant.cxx b/src/lexilla/lexers/LexBullant.cxx new file mode 100644 index 000000000..71ea0c0fa --- /dev/null +++ b/src/lexilla/lexers/LexBullant.cxx @@ -0,0 +1,234 @@ +// SciTE - Scintilla based Text Editor +// LexBullant.cxx - lexer for Bullant + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static int classifyWordBullant(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler) { + char s[100]; + s[0] = '\0'; + for (Sci_PositionU i = 0; i < end - start + 1 && i < 30; i++) { + s[i] = static_cast(tolower(styler[start + i])); + s[i + 1] = '\0'; + } + int lev= 0; + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')){ + chAttr = SCE_C_NUMBER; + } + else { + if (keywords.InList(s)) { + chAttr = SCE_C_WORD; + if (strcmp(s, "end") == 0) + lev = -1; + else if (strcmp(s, "method") == 0 || + strcmp(s, "case") == 0 || + strcmp(s, "class") == 0 || + strcmp(s, "debug") == 0 || + strcmp(s, "test") == 0 || + strcmp(s, "if") == 0 || + strcmp(s, "lock") == 0 || + strcmp(s, "transaction") == 0 || + strcmp(s, "trap") == 0 || + strcmp(s, "until") == 0 || + strcmp(s, "while") == 0) + lev = 1; + } + } + styler.ColourTo(end, chAttr); + return lev; +} + +static void ColouriseBullantDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + + styler.StartAt(startPos); + + bool fold = styler.GetPropertyInt("fold") != 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + + int state = initStyle; + if (state == SCE_C_STRINGEOL) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + Sci_PositionU lengthDoc = startPos + length; + int visibleChars = 0; + styler.StartSegment(startPos); + int endFoundThisLine = 0; + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + endFoundThisLine = 0; + if (state == SCE_C_STRINGEOL) { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + levelPrev = levelCurrent; + } + visibleChars = 0; + +/* int indentBlock = GetLineIndentation(lineCurrent); + if (blockChange==1){ + lineCurrent++; + int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize); + } else if (blockChange==-1) { + indentBlock -= indentSize; + if (indentBlock < 0) + indentBlock = 0; + SetLineIndentation(lineCurrent, indentBlock); + lineCurrent++; + } + blockChange=0; +*/ } + if (!(IsASCII(ch) && isspace(ch))) + visibleChars++; + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (iswordstart(ch)) { + styler.ColourTo(i-1, state); + state = SCE_C_IDENTIFIER; + } else if (ch == '@' && chNext == 'o') { + if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENT; + } + } else if (ch == '#') { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + styler.ColourTo(i-1, state); + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i-1, state); + styler.ColourTo(i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!iswordchar(ch)) { + int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler); + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '#') { + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i, SCE_C_OPERATOR); + } + if (endFoundThisLine == 0) + levelCurrent+=levelChange; + if (levelChange == -1) + endFoundThisLine=1; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '@' && chNext == 'o') { + if (styler.SafeGetCharAt(i+2) == 'n') { + styler.ColourTo(i+2, state); + state = SCE_C_DEFAULT; + i+=2; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } else if (chNext == '\r' || chNext == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } + } else if (state == SCE_C_CHARACTER) { + if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } else if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\'') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + } + chPrev = ch; + } + styler.ColourTo(lengthDoc - 1, state); + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + //styler.SetLevel(lineCurrent, levelCurrent | flagsNext); + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + + } +} + +static const char * const bullantWordListDesc[] = { + "Keywords", + 0 +}; + +extern const LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc); diff --git a/src/lexilla/lexers/LexCIL.cxx b/src/lexilla/lexers/LexCIL.cxx new file mode 100644 index 000000000..f224b7636 --- /dev/null +++ b/src/lexilla/lexers/LexCIL.cxx @@ -0,0 +1,410 @@ +// Scintilla source code edit control +/** @file LexCIL.cxx + ** Lexer for Common Intermediate Language + ** Written by Jad Altahan (github.com/xv) + ** CIL manual: https://www.ecma-international.org/publications/standards/Ecma-335.htm + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + // Use an unnamed namespace to protect the functions and classes from name conflicts + +bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +bool IsOperator(const int ch) { + if ((ch < 0x80) && (isalnum(ch))) + return false; + + if (strchr("!%&*+-/<=>@^|~()[]{}", ch)) { + return true; + } + + return false; +} + +constexpr bool IsStreamCommentStyle(const int style) noexcept { + return style == SCE_CIL_COMMENT; +} + +struct OptionsCIL { + bool fold; + bool foldComment; + bool foldCommentMultiline; + bool foldCompact; + + OptionsCIL() { + fold = true; + foldComment = false; + foldCommentMultiline = true; + foldCompact = true; + } +}; + +static const char *const cilWordListDesc[] = { + "Primary CIL keywords", + "Metadata", + "Opcode instructions", + 0 +}; + +struct OptionSetCIL : public OptionSet { + OptionSetCIL() { + DefineProperty("fold", &OptionsCIL::fold); + DefineProperty("fold.comment", &OptionsCIL::foldComment); + + DefineProperty("fold.cil.comment.multiline", &OptionsCIL::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.compact", &OptionsCIL::foldCompact); + + DefineWordListSets(cilWordListDesc); + } +}; + +LexicalClass lexicalClasses[] = { + // Lexer CIL SCLEX_CIL SCE_CIL_: + 0, "SCE_CIL_DEFAULT", "default", "White space", + 1, "SCE_CIL_COMMENT", "comment", "Multi-line comment", + 2, "SCE_CIL_COMMENTLINE", "comment line", "Line comment", + 3, "SCE_CIL_WORD", "keyword", "Keyword 1", + 4, "SCE_CIL_WORD2", "keyword", "Keyword 2", + 5, "SCE_CIL_WORD3", "keyword", "Keyword 3", + 6, "SCE_CIL_STRING", "literal string", "Double quoted string", + 7, "SCE_CIL_LABEL", "label", "Code label", + 8, "SCE_CIL_OPERATOR", "operator", "Operators", + 9, "SCE_CIL_STRINGEOL", "error literal string", "String is not closed", + 10, "SCE_CIL_IDENTIFIER", "identifier", "Identifiers", +}; + +} + +class LexerCIL : public DefaultLexer { + WordList keywords, keywords2, keywords3; + OptionsCIL options; + OptionSetCIL osCIL; + +public: + LexerCIL() : DefaultLexer("cil", SCLEX_CIL, lexicalClasses, ELEMENTS(lexicalClasses)) { } + + virtual ~LexerCIL() { } + + void SCI_METHOD Release() override { + delete this; + } + + int SCI_METHOD Version() const override { + return lvRelease5; + } + + const char * SCI_METHOD PropertyNames() override { + return osCIL.PropertyNames(); + } + + int SCI_METHOD PropertyType(const char *name) override { + return osCIL.PropertyType(name); + } + + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osCIL.DescribeProperty(name); + } + + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + + const char * SCI_METHOD PropertyGet(const char* key) override { + return osCIL.PropertyGet(key); + } + + const char * SCI_METHOD DescribeWordListSets() override { + return osCIL.DescribeWordListSets(); + } + + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + + int SCI_METHOD LineEndTypesSupported() override { + return SC_LINE_END_TYPE_UNICODE; + } + + int SCI_METHOD PrimaryStyleFromStyle(int style) override { + return style; + } + + static ILexer5 *LexerFactoryCIL() { + return new LexerCIL(); + } +}; + +Sci_Position SCI_METHOD LexerCIL::PropertySet(const char *key, const char *val) { + if (osCIL.PropertySet(&options, key, val)) { + return 0; + } + + return -1; +} + +Sci_Position SCI_METHOD LexerCIL::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + } + + Sci_Position firstModification = -1; + + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + + return firstModification; +} + +void SCI_METHOD LexerCIL::Lex(Sci_PositionU startPos, Sci_Position length, + int initStyle, IDocument *pAccess) { + if (initStyle == SCE_CIL_STRINGEOL) { + initStyle = SCE_CIL_DEFAULT; + } + + Accessor styler(pAccess, NULL); + StyleContext sc(startPos, length, initStyle, styler); + + bool identAtLineStart = false, // Checks if an identifier is at line start (ignoring spaces) + canStyleLabels = false; // Checks if conditions are met to style SCE_CIL_LABEL + + for (; sc.More(); sc.Forward()) { + if (sc.atLineStart) { + if (sc.state == SCE_CIL_STRING) { + sc.SetState(SCE_CIL_STRING); + } + + identAtLineStart = true; + } + + // Handle string line continuation + if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r') && + (sc.state == SCE_CIL_STRING)) { + sc.Forward(); + + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + + continue; + } + + switch (sc.state) { + case SCE_CIL_OPERATOR: + sc.SetState(SCE_CIL_DEFAULT); + break; + case SCE_CIL_IDENTIFIER: + if (!IsAWordChar(sc.ch)) { + if (canStyleLabels && (sc.ch == ':' && sc.chNext != ':')) { + sc.ChangeState(SCE_CIL_LABEL); + sc.ForwardSetState(SCE_CIL_DEFAULT); + } else { + char kwSize[100]; + sc.GetCurrent(kwSize, sizeof(kwSize)); + int style = SCE_CIL_IDENTIFIER; + + if (keywords.InList(kwSize)) { + style = SCE_CIL_WORD; + } else if (keywords2.InList(kwSize)) { + style = SCE_CIL_WORD2; + } else if (keywords3.InList(kwSize)) { + style = SCE_CIL_WORD3; + } + + sc.ChangeState(style); + sc.SetState(SCE_CIL_DEFAULT); + } + } + break; + case SCE_CIL_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_CIL_DEFAULT); + } + break; + case SCE_CIL_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_CIL_DEFAULT); + } + break; + case SCE_CIL_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '"') { + sc.ForwardSetState(SCE_CIL_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_CIL_STRINGEOL); + sc.ForwardSetState(SCE_CIL_DEFAULT); + } + break; + } + + if (sc.state == SCE_CIL_DEFAULT) { + // String + if (sc.ch == '"') { + sc.SetState(SCE_CIL_STRING); + } + // Keyword + else if (IsAWordChar(sc.ch)) { + // Allow setting SCE_CIL_LABEL style only if the label is the + // first token in the line and does not start with a dot or a digit + canStyleLabels = identAtLineStart && !(sc.ch == '.' || IsADigit(sc.ch)); + sc.SetState(SCE_CIL_IDENTIFIER); + } + // Multi-line comment + else if (sc.Match('/', '*')) { + sc.SetState(SCE_CIL_COMMENT); + sc.Forward(); + } + // Line comment + else if (sc.Match('/', '/')) { + sc.SetState(SCE_CIL_COMMENTLINE); + } + // Operators + else if (IsOperator(sc.ch)) { + sc.SetState(SCE_CIL_OPERATOR); + } + } + + if (!IsASpace(sc.ch)) { + identAtLineStart = false; + } + } + + sc.Complete(); +} + +void SCI_METHOD LexerCIL::Fold(Sci_PositionU startPos, Sci_Position length, + int initStyle, IDocument *pAccess) { + if (!options.fold) { + return; + } + + LexAccessor styler(pAccess); + + const Sci_PositionU endPos = startPos + length; + Sci_Position lineCurrent = styler.GetLine(startPos); + + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; + + int style = initStyle; + int styleNext = styler.StyleAt(startPos); + int levelNext = levelCurrent; + int visibleChars = 0; + + char chNext = styler[startPos]; + + for (Sci_PositionU i = startPos; i < endPos; i++) { + const char ch = chNext; + int stylePrev = style; + + chNext = styler.SafeGetCharAt(i + 1); + style = styleNext; + styleNext = styler.StyleAt(i + 1); + + const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (options.foldComment && + options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + levelNext--; + } + } + + if (style == SCE_CIL_OPERATOR) { + if (ch == '{') { + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + + if (!IsASpace(ch)) { + visibleChars++; + } + + if (atEOL || (i == endPos - 1)) { + int lev = levelCurrent | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelCurrent < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + + lineCurrent++; + levelCurrent = levelNext; + + if (options.foldCompact && + i == static_cast(styler.Length() - 1)) { + styler.SetLevel(lineCurrent, lev | SC_FOLDLEVELWHITEFLAG); + } + + visibleChars = 0; + } + } +} + +extern const LexerModule lmCIL(SCLEX_CIL, LexerCIL::LexerFactoryCIL, "cil", cilWordListDesc); \ No newline at end of file diff --git a/src/lexilla/lexers/LexCLW.cxx b/src/lexilla/lexers/LexCLW.cxx new file mode 100644 index 000000000..1ada3d47d --- /dev/null +++ b/src/lexilla/lexers/LexCLW.cxx @@ -0,0 +1,683 @@ +// Scintilla source code edit control +/** @file LexCLW.cxx + ** Lexer for Clarion. + ** 2004/12/17 Updated Lexer + **/ +// Copyright 2003-2004 by Ron Schofield +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +// Is an end of line character +inline bool IsEOL(const int ch) { + + return(ch == '\n'); +} + +// Convert character to uppercase +static char CharacterUpper(char chChar) { + + if (chChar < 'a' || chChar > 'z') { + return(chChar); + } + else { + return(static_cast(chChar - 'a' + 'A')); + } +} + +// Convert string to uppercase +static void StringUpper(char *szString) { + + while (*szString) { + *szString = CharacterUpper(*szString); + szString++; + } +} + +// Is a label start character +inline bool IsALabelStart(const int iChar) { + + return(isalpha(iChar) || iChar == '_'); +} + +// Is a label character +inline bool IsALabelCharacter(const int iChar) { + + return(isalnum(iChar) || iChar == '_' || iChar == ':'); +} + +// Is the character is a ! and the the next character is not a ! +inline bool IsACommentStart(const int iChar) { + + return(iChar == '!'); +} + +// Is the character a Clarion hex character (ABCDEF) +inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) { + + // Case insensitive. + if (!bCaseSensitive) { + if (strchr("ABCDEFabcdef", iChar) != NULL) { + return(true); + } + } + // Case sensitive + else { + if (strchr("ABCDEF", iChar) != NULL) { + return(true); + } + } + return(false); +} + +// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex) +inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) { + + // Case insensitive. + if (!bCaseSensitive) { + // If character is a numeric base character + if (strchr("BOHboh", iChar) != NULL) { + return(true); + } + } + // Case sensitive + else { + // If character is a numeric base character + if (strchr("BOH", iChar) != NULL) { + return(true); + } + } + return(false); +} + +// Set the correct numeric constant state +inline bool SetNumericConstantState(StyleContext &scDoc) { + + int iPoints = 0; // Point counter + char cNumericString[512]; // Numeric string buffer + + // Buffer the current numberic string + scDoc.GetCurrent(cNumericString, sizeof(cNumericString)); + // Loop through the string until end of string (NULL termination) + for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) { + // Depending on the character + switch (cNumericString[iIndex]) { + // Is a . (point) + case '.' : + // Increment point counter + iPoints++; + break; + default : + break; + } + } + // If points found (can be more than one for improper formatted number + if (iPoints > 0) { + return(true); + } + // Else no points found + else { + return(false); + } +} + +// Get the next word in uppercase from the current position (keyword lookahead) +inline bool GetNextWordUpper(Accessor &styler, Sci_PositionU uiStartPos, Sci_Position iLength, char *cWord) { + + Sci_PositionU iIndex = 0; // Buffer Index + + // Loop through the remaining string from the current position + for (Sci_Position iOffset = uiStartPos; iOffset < iLength; iOffset++) { + // Get the character from the buffer using the offset + char cCharacter = styler[iOffset]; + if (IsEOL(cCharacter)) { + break; + } + // If the character is alphabet character + if (isalpha(cCharacter)) { + // Add UPPERCASE character to the word buffer + cWord[iIndex++] = CharacterUpper(cCharacter); + } + } + // Add null termination + cWord[iIndex] = '\0'; + // If no word was found + if (iIndex == 0) { + // Return failure + return(false); + } + // Else word was found + else { + // Return success + return(true); + } +} + +// Clarion Language Colouring Procedure +static void ColouriseClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { + + int iParenthesesLevel = 0; // Parenthese Level + int iColumn1Label = false; // Label starts in Column 1 + + WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords + WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives + WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions + WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions + WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types + WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes + WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates + WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels) + WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels) + + const char wlProcReservedKeywordList[] = + "PROCEDURE FUNCTION"; + WordList wlProcReservedKeywords; + wlProcReservedKeywords.Set(wlProcReservedKeywordList); + + const char wlCompilerKeywordList[] = + "COMPILE OMIT"; + WordList wlCompilerKeywords; + wlCompilerKeywords.Set(wlCompilerKeywordList); + + const char wlLegacyStatementsList[] = + "BOF EOF FUNCTION POINTER SHARE"; + WordList wlLegacyStatements; + wlLegacyStatements.Set(wlLegacyStatementsList); + + StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler); + + // lex source code + for (; scDoc.More(); scDoc.Forward()) + { + // + // Determine if the current state should terminate. + // + + // Label State Handling + if (scDoc.state == SCE_CLW_LABEL) { + // If the character is not a valid label + if (!IsALabelCharacter(scDoc.ch)) { + // If the character is a . (dot syntax) + if (scDoc.ch == '.') { + // Turn off column 1 label flag as label now cannot be reserved work + iColumn1Label = false; + // Uncolour the . (dot) to default state, move forward one character, + // and change back to the label state. + scDoc.SetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + scDoc.SetState(SCE_CLW_LABEL); + } + // Else check label + else { + char cLabel[512]; // Label buffer + // Buffer the current label string + scDoc.GetCurrent(cLabel,sizeof(cLabel)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cLabel); + } + // Else if UPPERCASE label string is in the Clarion compiler keyword list + if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){ + // change the label to error state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Else if UPPERCASE label string is in the Clarion reserved keyword list + else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){ + // change the label to error state + scDoc.ChangeState(SCE_CLW_ERROR); + } + // Else if UPPERCASE label string is + else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { + char cWord[512]; // Word buffer + // Get the next word from the current position + if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) { + // If the next word is a procedure reserved word + if (wlProcReservedKeywords.InList(cWord)) { + // Change the label to error state + scDoc.ChangeState(SCE_CLW_ERROR); + } + } + } + // Else if label string is in the compiler directive keyword list + else if (wlCompilerDirectives.InList(cLabel)) { + // change the state to compiler directive state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Terminate the label state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + } + // Keyword State Handling + else if (scDoc.state == SCE_CLW_KEYWORD) { + // If character is : (colon) + if (scDoc.ch == ':') { + char cEquate[512]; // Equate buffer + // Move forward to include : (colon) in buffer + scDoc.Forward(); + // Buffer the equate string + scDoc.GetCurrent(cEquate,sizeof(cEquate)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cEquate); + } + // If statement string is in the equate list + if (wlStandardEquates.InList(cEquate)) { + // Change to equate state + scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); + } + } + // If the character is not a valid label character + else if (!IsALabelCharacter(scDoc.ch)) { + char cStatement[512]; // Statement buffer + // Buffer the statement string + scDoc.GetCurrent(cStatement,sizeof(cStatement)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cStatement); + } + // If statement string is in the Clarion keyword list + if (wlClarionKeywords.InList(cStatement)) { + // Change the statement string to the Clarion keyword state + scDoc.ChangeState(SCE_CLW_KEYWORD); + } + // Else if statement string is in the compiler directive keyword list + else if (wlCompilerDirectives.InList(cStatement)) { + // Change the statement string to the compiler directive state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Else if statement string is in the runtime expressions keyword list + else if (wlRuntimeExpressions.InList(cStatement)) { + // Change the statement string to the runtime expressions state + scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS); + } + // Else if statement string is in the builtin procedures and functions keyword list + else if (wlBuiltInProcsFuncs.InList(cStatement)) { + // Change the statement string to the builtin procedures and functions state + scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION); + } + // Else if statement string is in the tructures and data types keyword list + else if (wlStructsDataTypes.InList(cStatement)) { + // Change the statement string to the structures and data types state + scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE); + } + // Else if statement string is in the procedure attribute keyword list + else if (wlAttributes.InList(cStatement)) { + // Change the statement string to the procedure attribute state + scDoc.ChangeState(SCE_CLW_ATTRIBUTE); + } + // Else if statement string is in the standard equate keyword list + else if (wlStandardEquates.InList(cStatement)) { + // Change the statement string to the standard equate state + scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); + } + // Else if statement string is in the deprecated or legacy keyword list + else if (wlLegacyStatements.InList(cStatement)) { + // Change the statement string to the standard equate state + scDoc.ChangeState(SCE_CLW_DEPRECATED); + } + // Else the statement string doesn't match any work list + else { + // Change the statement string to the default state + scDoc.ChangeState(SCE_CLW_DEFAULT); + } + // Terminate the keyword state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + // String State Handling + else if (scDoc.state == SCE_CLW_STRING) { + // If the character is an ' (single quote) + if (scDoc.ch == '\'') { + // Set the state to default and move forward colouring + // the ' (single quote) as default state + // terminating the string state + scDoc.SetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + } + // If the next character is an ' (single quote) + if (scDoc.chNext == '\'') { + // Move forward one character and set to default state + // colouring the next ' (single quote) as default state + // terminating the string state + scDoc.ForwardSetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + } + } + // Picture String State Handling + else if (scDoc.state == SCE_CLW_PICTURE_STRING) { + // If the character is an ( (open parenthese) + if (scDoc.ch == '(') { + // Increment the parenthese level + iParenthesesLevel++; + } + // Else if the character is a ) (close parenthese) + else if (scDoc.ch == ')') { + // If the parenthese level is set to zero + // parentheses matched + if (!iParenthesesLevel) { + scDoc.SetState(SCE_CLW_DEFAULT); + } + // Else parenthese level is greater than zero + // still looking for matching parentheses + else { + // Decrement the parenthese level + iParenthesesLevel--; + } + } + } + // Standard Equate State Handling + else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) { + if (!isalnum(scDoc.ch)) { + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + // Integer Constant State Handling + else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) { + // If the character is not a digit (0-9) + // or character is not a hexidecimal character (A-F) + // or character is not a . (point) + // or character is not a numberic base character (B,O,H) + if (!(isdigit(scDoc.ch) + || IsAHexCharacter(scDoc.ch, bCaseSensitive) + || scDoc.ch == '.' + || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { + // If the number was a real + if (SetNumericConstantState(scDoc)) { + // Colour the matched string to the real constant state + scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); + } + // Else the number was an integer + else { + // Colour the matched string to an integer constant state + scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT); + } + // Terminate the integer constant state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + + // + // Determine if a new state should be entered. + // + + // Beginning of Line Handling + if (scDoc.atLineStart) { + // Reset the column 1 label flag + iColumn1Label = false; + // If column 1 character is a label start character + if (IsALabelStart(scDoc.ch)) { + // Label character is found in column 1 + // so set column 1 label flag and clear last column 1 label + iColumn1Label = true; + // Set the state to label + scDoc.SetState(SCE_CLW_LABEL); + } + // else if character is a space or tab + else if (IsASpace(scDoc.ch)){ + // Set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + // else if comment start (!) or is an * (asterisk) + else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) { + // then set the state to comment. + scDoc.SetState(SCE_CLW_COMMENT); + } + // else the character is a ? (question mark) + else if (scDoc.ch == '?') { + // Change to the compiler directive state, move forward, + // colouring the ? (question mark), change back to default state. + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + scDoc.Forward(); + scDoc.SetState(SCE_CLW_DEFAULT); + } + // else an invalid character in column 1 + else { + // Set to error state + scDoc.SetState(SCE_CLW_ERROR); + } + } + // End of Line Handling + else if (scDoc.atLineEnd) { + // Reset to the default state at the end of each line. + scDoc.SetState(SCE_CLW_DEFAULT); + } + // Default Handling + else { + // If in default state + if (scDoc.state == SCE_CLW_DEFAULT) { + // If is a letter could be a possible statement + if (isalpha(scDoc.ch)) { + // Set the state to Clarion Keyword and verify later + scDoc.SetState(SCE_CLW_KEYWORD); + } + // else is a number + else if (isdigit(scDoc.ch)) { + // Set the state to Integer Constant and verify later + scDoc.SetState(SCE_CLW_INTEGER_CONSTANT); + } + // else if the start of a comment or a | (line continuation) + else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') { + // then set the state to comment. + scDoc.SetState(SCE_CLW_COMMENT); + } + // else if the character is a ' (single quote) + else if (scDoc.ch == '\'') { + // If the character is also a ' (single quote) + // Embedded Apostrophe + if (scDoc.chNext == '\'') { + // Move forward colouring it as default state + scDoc.ForwardSetState(SCE_CLW_DEFAULT); + } + else { + // move to the next character and then set the state to comment. + scDoc.ForwardSetState(SCE_CLW_STRING); + } + } + // else the character is an @ (ampersand) + else if (scDoc.ch == '@') { + // Case insensitive. + if (!bCaseSensitive) { + // If character is a valid picture token character + if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) { + // Set to the picture string state + scDoc.SetState(SCE_CLW_PICTURE_STRING); + } + } + // Case sensitive + else { + // If character is a valid picture token character + if (strchr("DEKNPST", scDoc.chNext) != NULL) { + // Set the picture string state + scDoc.SetState(SCE_CLW_PICTURE_STRING); + } + } + } + } + } + } + // lexing complete + scDoc.Complete(); +} + +// Clarion Language Case Sensitive Colouring Procedure +static void ColouriseClarionDocSensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { + + ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true); +} + +// Clarion Language Case Insensitive Colouring Procedure +static void ColouriseClarionDocInsensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { + + ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false); +} + +// Fill Buffer + +static void FillBuffer(Sci_PositionU uiStart, Sci_PositionU uiEnd, Accessor &accStyler, char *szBuffer, Sci_PositionU uiLength) { + + Sci_PositionU uiPos = 0; + + while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) { + szBuffer[uiPos] = static_cast(toupper(accStyler[uiStart + uiPos])); + uiPos++; + } + szBuffer[uiPos] = '\0'; +} + +// Classify Clarion Fold Point + +static int ClassifyClarionFoldPoint(int iLevel, const char* szString) { + + if (!(isdigit(szString[0]) || (szString[0] == '.'))) { + if (strcmp(szString, "PROCEDURE") == 0) { + // iLevel = SC_FOLDLEVELBASE + 1; + } + else if (strcmp(szString, "MAP") == 0 || + strcmp(szString,"ACCEPT") == 0 || + strcmp(szString,"BEGIN") == 0 || + strcmp(szString,"CASE") == 0 || + strcmp(szString,"EXECUTE") == 0 || + strcmp(szString,"IF") == 0 || + strcmp(szString,"ITEMIZE") == 0 || + strcmp(szString,"INTERFACE") == 0 || + strcmp(szString,"JOIN") == 0 || + strcmp(szString,"LOOP") == 0 || + strcmp(szString,"MODULE") == 0 || + strcmp(szString,"RECORD") == 0) { + iLevel++; + } + else if (strcmp(szString, "APPLICATION") == 0 || + strcmp(szString, "CLASS") == 0 || + strcmp(szString, "DETAIL") == 0 || + strcmp(szString, "FILE") == 0 || + strcmp(szString, "FOOTER") == 0 || + strcmp(szString, "FORM") == 0 || + strcmp(szString, "GROUP") == 0 || + strcmp(szString, "HEADER") == 0 || + strcmp(szString, "INTERFACE") == 0 || + strcmp(szString, "MENU") == 0 || + strcmp(szString, "MENUBAR") == 0 || + strcmp(szString, "OLE") == 0 || + strcmp(szString, "OPTION") == 0 || + strcmp(szString, "QUEUE") == 0 || + strcmp(szString, "REPORT") == 0 || + strcmp(szString, "SHEET") == 0 || + strcmp(szString, "TAB") == 0 || + strcmp(szString, "TOOLBAR") == 0 || + strcmp(szString, "VIEW") == 0 || + strcmp(szString, "WINDOW") == 0) { + iLevel++; + } + else if (strcmp(szString, "END") == 0 || + strcmp(szString, "UNTIL") == 0 || + strcmp(szString, "WHILE") == 0) { + iLevel--; + } + } + return(iLevel); +} + +// Clarion Language Folding Procedure +static void FoldClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *[], Accessor &accStyler) { + + Sci_PositionU uiEndPos = uiStartPos + iLength; + Sci_Position iLineCurrent = accStyler.GetLine(uiStartPos); + int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK; + int iLevelCurrent = iLevelPrev; + char chNext = accStyler[uiStartPos]; + int iStyle = iInitStyle; + int iStyleNext = accStyler.StyleAt(uiStartPos); + int iVisibleChars = 0; + Sci_Position iLastStart = 0; + + for (Sci_PositionU uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) { + + char chChar = chNext; + chNext = accStyler.SafeGetCharAt(uiPos + 1); + int iStylePrev = iStyle; + iStyle = iStyleNext; + iStyleNext = accStyler.StyleAt(uiPos + 1); + bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n'); + + if (iStylePrev == SCE_CLW_DEFAULT) { + if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) { + // Store last word start point. + iLastStart = uiPos; + } + } + + if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) { + if(iswordchar(chChar) && !iswordchar(chNext)) { + char chBuffer[100]; + FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer)); + iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer); + // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) { + // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE); + // iLevelPrev = SC_FOLDLEVELBASE; + // } + } + } + + if (bEOL) { + int iLevel = iLevelPrev; + if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0)) + iLevel |= SC_FOLDLEVELHEADERFLAG; + if (iLevel != accStyler.LevelAt(iLineCurrent)) { + accStyler.SetLevel(iLineCurrent,iLevel); + } + iLineCurrent++; + iLevelPrev = iLevelCurrent; + iVisibleChars = 0; + } + + if (!isspacechar(chChar)) + iVisibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags + // as they will be filled in later. + int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext); +} + +// Word List Descriptions +static const char * const rgWordListDescriptions[] = { + "Clarion Keywords", + "Compiler Directives", + "Built-in Procedures and Functions", + "Runtime Expressions", + "Structure and Data Types", + "Attributes", + "Standard Equates", + "Reserved Words (Labels)", + "Reserved Words (Procedure Labels)", + 0, +}; + +// Case Sensitive Clarion Language Lexer +extern const LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions); + +// Case Insensitive Clarion Language Lexer +extern const LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions); diff --git a/src/lexilla/lexers/LexCOBOL.cxx b/src/lexilla/lexers/LexCOBOL.cxx new file mode 100644 index 000000000..c52f0c27a --- /dev/null +++ b/src/lexilla/lexers/LexCOBOL.cxx @@ -0,0 +1,387 @@ +// Scintilla source code edit control +/** @file LexCOBOL.cxx + ** Lexer for COBOL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele September 2002 + ** Updated by Mathias Rauen May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to COBOL + **/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +#define IN_DIVISION 0x01 +#define IN_DECLARATIVES 0x02 +#define IN_SECTION 0x04 +#define IN_PARAGRAPH 0x08 +#define IN_FLAGS 0xF +#define NOT_HEADER 0x10 + +inline bool isCOBOLoperator(char ch) + { + return isoperator(ch); + } + +inline bool isCOBOLwordchar(char ch) + { + return IsASCII(ch) && (isalnum(ch) || ch == '-'); + + } + +inline bool isCOBOLwordstart(char ch) + { + return IsASCII(ch) && isalnum(ch); + } + +static int CountBits(int nBits) + { + int count = 0; + for (int i = 0; i < 32; ++i) + { + count += nBits & 1; + nBits >>= 1; + } + return count; + } + +static void getRange(Sci_PositionU start, + Sci_PositionU end, + Accessor &styler, + char *s, + Sci_PositionU len) { + Sci_PositionU i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void ColourTo(Accessor &styler, Sci_PositionU end, unsigned int attr) { + styler.ColourTo(end, attr); +} + + +static int classifyWordCOBOL(Sci_PositionU start, Sci_PositionU end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) { + int ret = 0; + + char s[100]; + s[0] = '\0'; + s[1] = '\0'; + getRange(start, end, styler, s, sizeof(s)); + + int chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) { + chAttr = SCE_C_NUMBER; + char *p = s + 1; + while (*p) { + if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) { + chAttr = SCE_C_IDENTIFIER; + break; + } + ++p; + } + } + if (chAttr == SCE_C_IDENTIFIER) { + WordList& a_keywords = *keywordlists[0]; + WordList& b_keywords = *keywordlists[1]; + WordList& c_keywords = *keywordlists[2]; + + if (a_keywords.InList(s)) { + chAttr = SCE_C_WORD; + } + else if (b_keywords.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (c_keywords.InList(s)) { + chAttr = SCE_C_UUID; + } + } + if (*bAarea) { + if (strcmp(s, "division") == 0) { + ret = IN_DIVISION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "declaratives") == 0) { + ret = IN_DIVISION | IN_DECLARATIVES; + if (nContainment & IN_DECLARATIVES) + ret |= NOT_HEADER | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "section") == 0) { + ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) { + ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER; + } else { + ret = nContainment | IN_PARAGRAPH; + } + } + ColourTo(styler, end, chAttr); + return ret; +} + +static void ColouriseCOBOLDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + Sci_PositionU lengthDoc = startPos + length; + + int nContainment; + + Sci_Position currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + nContainment = styler.GetLineState(currentLine); + nContainment &= ~NOT_HEADER; + } else { + styler.SetLineState(currentLine, 0); + nContainment = 0; + } + + styler.StartSegment(startPos); + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + ++column; + + if (bNewLine) { + column = 0; + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool bSetNewLine = false; + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + styler.SetLineState(currentLine, nContainment); + currentLine++; + bSetNewLine = true; + if (nContainment & NOT_HEADER) + nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isCOBOLwordstart(ch) || (ch == '$' && IsASCII(chNext) && isalpha(chNext))) { + ColourTo(styler, i-1, state); + state = SCE_C_IDENTIFIER; + } else if (column == 6 && (ch == '*' || ch == '/')) { + // Cobol comment line: asterisk in column 7. + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (ch == '*' && chNext == '>') { + // Cobol inline comment: asterisk, followed by greater than. + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '*' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '/' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '*' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (column == 0 && ch == '/' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (ch == '"') { + ColourTo(styler, i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + ColourTo(styler, i-1, state); + state = SCE_C_CHARACTER; + } else if (ch == '?' && column == 0) { + ColourTo(styler, i-1, state); + state = SCE_C_PREPROCESSOR; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i-1, state); + ColourTo(styler, i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isCOBOLwordchar(ch)) { + int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea); + + if(lStateChange != 0) { + styler.SetLineState(currentLine, lStateChange); + nContainment = lStateChange; + } + + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (column == 6 && (ch == '*' || ch == '/')) { + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR); + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '\r' || ch == '\n') { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast(startPos))))) { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } else if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_CHARACTER) { + if (ch == '\'') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } + } + chPrev = ch; + bNewLine = bSetNewLine; + if (bNewLine) + { + bAarea = false; + } + } + ColourTo(styler, lengthDoc - 1, state); +} + +static void FoldCOBOLDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], + Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF; + char chNext = styler[startPos]; + + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + bool bComment = false; + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + ++column; + + if (bNewLine) { + column = 0; + bComment = (ch == '*' || ch == '/' || ch == '?'); + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (atEOL) { + int nContainment = styler.GetLineState(lineCurrent); + int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE; + if (bAarea && !bComment) + --lev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) { + // this level is at the same level or less than the previous line + // therefore these is nothing for the previous header to collapse, so remove the header + styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); + } + levelPrev = lev; + visibleChars = 0; + bAarea = false; + bNewLine = true; + lineCurrent++; + } else { + bNewLine = false; + } + + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const COBOLWordListDesc[] = { + "A Keywords", + "B Keywords", + "Extended Keywords", + 0 +}; + +extern const LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc); diff --git a/src/lexilla/lexers/LexCPP.cxx b/src/lexilla/lexers/LexCPP.cxx new file mode 100644 index 000000000..f7c38348d --- /dev/null +++ b/src/lexilla/lexers/LexCPP.cxx @@ -0,0 +1,1845 @@ +// Scintilla source code edit control +/** @file LexCPP.cxx + ** Lexer for C++, C, Java, and JavaScript. + ** Further folding features and configuration properties added by "Udo Lechner" + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SparseState.h" +#include "SubStyles.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + // Use an unnamed namespace to protect the functions and classes from name conflicts + +constexpr bool IsSpaceEquiv(int state) noexcept { + return (state <= SCE_C_COMMENTDOC) || + // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE + (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || + (state == SCE_C_COMMENTDOCKEYWORDERROR); +} + +// Preconditions: sc.currentPos points to a character after '+' or '-'. +// The test for pos reaching 0 should be redundant, +// and is in only for safety measures. +// Limitation: this code will give the incorrect answer for code like +// a = b+++/ptn/... +// Putting a space between the '++' post-inc operator and the '+' binary op +// fixes this, and is highly recommended for readability anyway. +bool FollowsPostfixOperator(const StyleContext &sc, LexAccessor &styler) { + Sci_Position pos = sc.currentPos; + while (--pos > 0) { + const char ch = styler[pos]; + if (ch == '+' || ch == '-') { + return styler[pos - 1] == ch; + } + } + return false; +} + +bool followsReturnKeyword(const StyleContext &sc, LexAccessor &styler) { + // Don't look at styles, so no need to flush. + Sci_Position pos = sc.currentPos; + const Sci_Position currentLine = styler.GetLine(pos); + const Sci_Position lineStartPos = styler.LineStart(currentLine); + while (--pos > lineStartPos) { + const char ch = styler.SafeGetCharAt(pos); + if (ch != ' ' && ch != '\t') { + break; + } + } + const char *retBack = "nruter"; + const char *s = retBack; + while (*s + && pos >= lineStartPos + && styler.SafeGetCharAt(pos) == *s) { + s++; + pos--; + } + return !*s; +} + +constexpr bool IsOperatorOrSpace(int ch) noexcept { + return isoperator(ch) || IsASpace(ch); +} + +bool OnlySpaceOrTab(std::string_view s) noexcept { + for (const char ch : s) { + if (!IsASpaceOrTab(ch)) + return false; + } + return true; +} + +using Tokens = std::vector; + +Tokens StringSplit(const std::string &text, int separator) { + Tokens vs(text.empty() ? 0 : 1); + for (const char ch : text) { + if (ch == separator) { + vs.emplace_back(); + } else { + vs.back() += ch; + } + } + return vs; +} + +struct BracketPair { + Tokens::iterator itBracket; + Tokens::iterator itEndBracket; +}; + +BracketPair FindBracketPair(Tokens &tokens) { + const Tokens::iterator itBracket = std::find(tokens.begin(), tokens.end(), "("); + if (itBracket != tokens.end()) { + size_t nest = 0; + for (Tokens::iterator itTok = itBracket; itTok != tokens.end(); ++itTok) { + if (*itTok == "(") { + nest++; + } else if (*itTok == ")") { + nest--; + if (nest == 0) { + return { itBracket, itTok }; + } + } + } + } + return { tokens.end(), tokens.end() }; +} + +void highlightTaskMarker(StyleContext &sc, LexAccessor &styler, + int activity, const WordList &markerList, bool caseSensitive) { + if (IsOperatorOrSpace(sc.chPrev) && !IsOperatorOrSpace(sc.ch) && markerList.Length()) { + std::string marker; + for (Sci_PositionU currPos = sc.currentPos; true; currPos++) { + const char ch = styler.SafeGetCharAt(currPos); + if (IsOperatorOrSpace(ch)) { + break; + } + if (caseSensitive) + marker.push_back(ch); + else + marker.push_back(MakeLowerCase(ch)); + } + if (markerList.InList(marker)) { + sc.SetState(SCE_C_TASKMARKER|activity); + } + } +} + +const CharacterSet setHexDigits(CharacterSet::setDigits, "ABCDEFabcdef"); +const CharacterSet setOctDigits("01234567"); +const CharacterSet setNoneNumeric; + +class EscapeSequence { + const CharacterSet *escapeSetValid = nullptr; + int digitsLeft = 0; +public: + int outerState = SCE_C_DEFAULT; + EscapeSequence() = default; + void resetEscapeState(int state, int nextChar) noexcept { + digitsLeft = 0; + outerState = state; + escapeSetValid = &setNoneNumeric; + if (nextChar == 'U') { + digitsLeft = 9; + escapeSetValid = &setHexDigits; + } else if (nextChar == 'u') { + digitsLeft = 5; + escapeSetValid = &setHexDigits; + } else if (nextChar == 'x') { + digitsLeft = 5; + escapeSetValid = &setHexDigits; + } else if (setOctDigits.Contains(nextChar)) { + digitsLeft = 3; + escapeSetValid = &setOctDigits; + } + } + [[nodiscard]] bool atEscapeEnd(int currChar) const noexcept { + return (digitsLeft <= 0) || !escapeSetValid->Contains(currChar); + } + void consumeDigit() noexcept { + digitsLeft--; + } +}; + +std::string GetRestOfLine(LexAccessor &styler, Sci_Position start, bool allowSpace) { + std::string restOfLine; + Sci_Position line = styler.GetLine(start); + Sci_Position pos = start; + Sci_Position endLine = styler.LineEnd(line); + char ch = styler.SafeGetCharAt(start, '\n'); + while (pos < endLine) { + if (ch == '\\' && ((pos + 1) == endLine)) { + // Continuation line + line++; + pos = styler.LineStart(line); + endLine = styler.LineEnd(line); + ch = styler.SafeGetCharAt(pos, '\n'); + } else { + const char chNext = styler.SafeGetCharAt(pos + 1, '\n'); + if (ch == '/' && (chNext == '/' || chNext == '*')) + break; + if (allowSpace || (ch != ' ')) { + restOfLine += ch; + } + pos++; + ch = chNext; + } + } + return restOfLine; +} + +constexpr bool IsStreamCommentStyle(int style) noexcept { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +struct PPDefinition { + Sci_Position line; + std::string key; + std::string value; + bool isUndef; + std::string arguments; + PPDefinition(Sci_Position line_, std::string_view key_, std::string_view value_, bool isUndef_, std::string_view arguments_) : + line(line_), key(key_), value(value_), isUndef(isUndef_), arguments(arguments_) { + } +}; + +constexpr int inactiveFlag = 0x40; + +class LinePPState { + // Track the state of preprocessor conditionals to allow showing active and inactive + // code in different styles. + // Only works up to 31 levels of conditional nesting. + + // state is a bit mask with 1 bit per level + // bit is 1 for level if section inactive, so any bits set = inactive style + int state = 0; + // ifTaken is a bit mask with 1 bit per level + // bit is 1 for level if some branch at this level has been taken + int ifTaken = 0; + // level is the nesting level of #if constructs + int level = -1; + static const int maximumNestingLevel = 31; + [[nodiscard]] int maskLevel() const noexcept { + if (level >= 0) { + return 1 << level; + } + return 1; + } +public: + LinePPState() noexcept = default; + [[nodiscard]] bool ValidLevel() const noexcept { + return level >= 0 && level < maximumNestingLevel; + } + [[nodiscard]] bool IsActive() const noexcept { + return state == 0; + } + [[nodiscard]] bool IsInactive() const noexcept { + return state != 0; + } + [[nodiscard]] int ActiveState() const noexcept { + return state ? inactiveFlag : 0; + } + [[nodiscard]] bool CurrentIfTaken() const noexcept { + return (ifTaken & maskLevel()) != 0; + } + void StartSection(bool on) noexcept { + level++; + if (ValidLevel()) { + if (on) { + state &= ~maskLevel(); + ifTaken |= maskLevel(); + } else { + state |= maskLevel(); + ifTaken &= ~maskLevel(); + } + } + } + void EndSection() noexcept { + if (ValidLevel()) { + state &= ~maskLevel(); + ifTaken &= ~maskLevel(); + } + level--; + } + void InvertCurrentLevel() noexcept { + if (ValidLevel()) { + state ^= maskLevel(); + ifTaken |= maskLevel(); + } + } +}; + +// Hold the preprocessor state for each line seen. +// Currently one entry per line but could become sparse with just one entry per preprocessor line. +class PPStates { + std::vector vlls; +public: + [[nodiscard]] LinePPState ForLine(Sci_Position line) const noexcept { + if ((line > 0) && (vlls.size() > static_cast(line))) { + return vlls[line]; + } + return {}; + } + void Add(Sci_Position line, LinePPState lls) { + vlls.resize(line+1); + vlls[line] = lls; + } +}; + +enum class BackQuotedString : int { + None, + RawString, + TemplateLiteral, +}; + +// string interpolating state +struct InterpolatingState { + int state; + int braceCount; +}; + +struct Definition { + std::string_view name; + std::string_view value; + std::string_view arguments; +}; + +constexpr std::string_view TrimSpaceTab(std::string_view sv) noexcept { + while (!sv.empty() && IsASpaceOrTab(sv.front())) { + sv.remove_prefix(1); + } + return sv; +} + +// Parse a macro definition, either from a #define line in a file or from keywords. +// Either an object macro or a function macro () . +// VALUE is optional and is treated as "1" if missing. +// #define ALLOW_PRINT +// #define VERSION 37 +// #define VER(a,b) a*10+b +// Whitespace separates macro and value in files but keywords use '=' separator. +// 'endName' contains a set of characters that terminate the name of the macro. + +constexpr Definition ParseDefine(std::string_view definition, std::string_view endName) { + Definition ret; + definition = TrimSpaceTab(definition); + const size_t afterName = definition.find_first_of(endName); + if (afterName != std::string_view::npos) { + ret.name = definition.substr(0, afterName); + if (definition.at(afterName) == '(') { + // Macro + definition.remove_prefix(afterName+1); + const size_t closeBracket = definition.find(')'); + if (closeBracket != std::string_view::npos) { + ret.arguments = definition.substr(0, closeBracket); + definition.remove_prefix(closeBracket+1); + if (!definition.empty() && (endName.find(definition.front()) != std::string_view::npos)) { + definition.remove_prefix(1); + } + ret.value = definition; + } // else malformed as requires closing bracket + } else { + ret.value = definition.substr(afterName+1); + } + } else { + ret.name = definition; + ret.value = "1"; + } + return ret; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerCPP +struct OptionsCPP { + bool stylingWithinPreprocessor = false; + bool identifiersAllowDollars = true; + bool trackPreprocessor = true; + bool updatePreprocessor = true; + bool verbatimStringsAllowEscapes = false; + bool triplequotedStrings = false; + bool hashquotedStrings = false; + BackQuotedString backQuotedStrings = BackQuotedString::None; + bool escapeSequence = false; + bool fold = false; + bool foldSyntaxBased = true; + bool foldComment = false; + bool foldCommentMultiline = true; + bool foldCommentExplicit = true; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere = false; + bool foldPreprocessor = false; + bool foldPreprocessorAtElse = false; + bool foldCompact = false; + bool foldAtElse = false; +}; + +const char *const cppWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Global classes and typedefs", + "Preprocessor definitions", + "Task marker and error marker keywords", + nullptr, +}; + +struct OptionSetCPP : public OptionSet { + OptionSetCPP() { + DefineProperty("styling.within.preprocessor", &OptionsCPP::stylingWithinPreprocessor, + "For C++ code, determines whether all preprocessor code is styled in the " + "preprocessor style (0, the default) or only from the initial # to the end " + "of the command word(1)."); + + DefineProperty("lexer.cpp.allow.dollars", &OptionsCPP::identifiersAllowDollars, + "Set to 0 to disallow the '$' character in identifiers with the cpp lexer."); + + DefineProperty("lexer.cpp.track.preprocessor", &OptionsCPP::trackPreprocessor, + "Set to 1 to interpret #if/#else/#endif to grey out code that is not active."); + + DefineProperty("lexer.cpp.update.preprocessor", &OptionsCPP::updatePreprocessor, + "Set to 1 to update preprocessor definitions when #define found."); + + DefineProperty("lexer.cpp.verbatim.strings.allow.escapes", &OptionsCPP::verbatimStringsAllowEscapes, + "Set to 1 to allow verbatim strings to contain escape sequences."); + + DefineProperty("lexer.cpp.triplequoted.strings", &OptionsCPP::triplequotedStrings, + "Set to 1 to enable highlighting of triple-quoted strings."); + + DefineProperty("lexer.cpp.hashquoted.strings", &OptionsCPP::hashquotedStrings, + "Set to 1 to enable highlighting of hash-quoted strings."); + + DefineProperty("lexer.cpp.backquoted.strings", &OptionsCPP::backQuotedStrings, + "Set how to highlighting back-quoted strings. " + "0 (the default) no highlighting. " + "1 highlighted as Go raw string. " + "2 highlighted as JavaScript template literal."); + + DefineProperty("lexer.cpp.escape.sequence", &OptionsCPP::escapeSequence, + "Set to 1 to enable highlighting of escape sequences in strings"); + + DefineProperty("fold", &OptionsCPP::fold); + + DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.comment", &OptionsCPP::foldComment, + "This option enables folding multi-line comments and explicit fold points when using the C++ lexer. " + "Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} " + "at the end of a section that should fold."); + + DefineProperty("fold.cpp.comment.multiline", &OptionsCPP::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.cpp.comment.explicit", &OptionsCPP::foldCommentExplicit, + "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + + DefineProperty("fold.cpp.explicit.start", &OptionsCPP::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.cpp.explicit.end", &OptionsCPP::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.cpp.explicit.anywhere", &OptionsCPP::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.cpp.preprocessor.at.else", &OptionsCPP::foldPreprocessorAtElse, + "This option enables folding on a preprocessor #else or #endif line of an #if statement."); + + DefineProperty("fold.preprocessor", &OptionsCPP::foldPreprocessor, + "This option enables folding preprocessor directives when using the C++ lexer. " + "Includes C#'s explicit #region and #endregion folding directives."); + + DefineProperty("fold.compact", &OptionsCPP::foldCompact); + + DefineProperty("fold.at.else", &OptionsCPP::foldAtElse, + "This option enables C++ folding on a \"} else {\" line of an if statement."); + + DefineWordListSets(cppWordLists); + } +}; + +const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0}; + +LexicalClass lexicalClasses[] = { + // Lexer Cpp SCLEX_CPP SCE_C_: + 0, "SCE_C_DEFAULT", "default", "White space", + 1, "SCE_C_COMMENT", "comment", "Comment: /* */.", + 2, "SCE_C_COMMENTLINE", "comment line", "Line Comment: //.", + 3, "SCE_C_COMMENTDOC", "comment documentation", "Doc comment: block comments beginning with /** or /*!", + 4, "SCE_C_NUMBER", "literal numeric", "Number", + 5, "SCE_C_WORD", "keyword", "Keyword", + 6, "SCE_C_STRING", "literal string", "Double quoted string", + 7, "SCE_C_CHARACTER", "literal string character", "Single quoted string", + 8, "SCE_C_UUID", "literal uuid", "UUIDs (only in IDL)", + 9, "SCE_C_PREPROCESSOR", "preprocessor", "Preprocessor", + 10, "SCE_C_OPERATOR", "operator", "Operators", + 11, "SCE_C_IDENTIFIER", "identifier", "Identifiers", + 12, "SCE_C_STRINGEOL", "error literal string", "End of line where string is not closed", + 13, "SCE_C_VERBATIM", "literal string multiline raw", "Verbatim strings for C#", + 14, "SCE_C_REGEX", "literal regex", "Regular expressions for JavaScript", + 15, "SCE_C_COMMENTLINEDOC", "comment documentation line", "Doc Comment Line: line comments beginning with /// or //!.", + 16, "SCE_C_WORD2", "identifier", "Keywords2", + 17, "SCE_C_COMMENTDOCKEYWORD", "comment documentation keyword", "Comment keyword", + 18, "SCE_C_COMMENTDOCKEYWORDERROR", "error comment documentation keyword", "Comment keyword error", + 19, "SCE_C_GLOBALCLASS", "identifier", "Global class", + 20, "SCE_C_STRINGRAW", "literal string multiline raw", "Raw strings for C++0x", + 21, "SCE_C_TRIPLEVERBATIM", "literal string multiline raw", "Triple-quoted strings for Vala", + 22, "SCE_C_HASHQUOTEDSTRING", "literal string", "Hash-quoted strings for Pike", + 23, "SCE_C_PREPROCESSORCOMMENT", "comment preprocessor", "Preprocessor stream comment", + 24, "SCE_C_PREPROCESSORCOMMENTDOC", "comment preprocessor documentation", "Preprocessor stream doc comment", + 25, "SCE_C_USERLITERAL", "literal", "User defined literals", + 26, "SCE_C_TASKMARKER", "comment taskmarker", "Task Marker", + 27, "SCE_C_ESCAPESEQUENCE", "literal string escapesequence", "Escape sequence", +}; + +const int sizeLexicalClasses = static_cast(std::size(lexicalClasses)); + +} + +class LexerCPP : public ILexer5 { + bool caseSensitive; + CharacterSet setWord; + CharacterSet setNegationOp; + CharacterSet setAddOp; + CharacterSet setMultOp; + CharacterSet setRelOp; + CharacterSet setLogicalOp; + CharacterSet setWordStart; + PPStates vlls; + std::vector ppDefineHistory; + std::map> interpolatingAtEol; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList ppDefinitions; + WordList markerList; + struct SymbolValue { + std::string value; + std::string arguments; + SymbolValue() noexcept = default; + SymbolValue(std::string_view value_, std::string_view arguments_) : value(value_), arguments(arguments_) { + } + SymbolValue &operator = (const std::string &value_) { + value = value_; + arguments.clear(); + return *this; + } + [[nodiscard]] bool IsMacro() const noexcept { + return !arguments.empty(); + } + }; + using SymbolTable = std::map; + SymbolTable preprocessorDefinitionsStart; + OptionsCPP options; + OptionSetCPP osCPP; + EscapeSequence escapeSeq; + SparseState rawStringTerminators; + enum { ssIdentifier, ssDocKeyword }; + SubStyles subStyles{ styleSubable, SubStylesFirst, SubStylesAvailable, inactiveFlag }; + std::string returnBuffer; +public: + explicit LexerCPP(bool caseSensitive_) : + caseSensitive(caseSensitive_), + setWord(CharacterSet::setAlphaNum, "._", true), + setNegationOp("!"), + setAddOp("+-"), + setMultOp("*/%"), + setRelOp("=!<>"), + setLogicalOp("|&") { + } + // Deleted so LexerCPP objects can not be copied. + LexerCPP(const LexerCPP &) = delete; + LexerCPP(LexerCPP &&) = delete; + void operator=(const LexerCPP &) = delete; + void operator=(LexerCPP &&) = delete; + virtual ~LexerCPP() = default; + void SCI_METHOD Release() noexcept override { + delete this; + } + int SCI_METHOD Version() const noexcept override { + return lvRelease5; + } + const char *SCI_METHOD PropertyNames() override { + return osCPP.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osCPP.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) override { + return osCPP.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char *SCI_METHOD DescribeWordListSets() override { + return osCPP.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void *SCI_METHOD PrivateCall(int, void *) noexcept override { + return nullptr; + } + + int SCI_METHOD LineEndTypesSupported() noexcept override { + return SC_LINE_END_TYPE_UNICODE; + } + + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) override { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) override { + return subStyles.Length(styleBase); + } + int SCI_METHOD StyleFromSubStyle(int subStyle) override { + const int styleBase = subStyles.BaseStyle(MaskActive(subStyle)); + const int inactive = subStyle & inactiveFlag; + return styleBase | inactive; + } + int SCI_METHOD PrimaryStyleFromStyle(int style) noexcept override { + return MaskActive(style); + } + void SCI_METHOD FreeSubStyles() override { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override { + subStyles.SetIdentifiers(style, identifiers); + } + int SCI_METHOD DistanceToSecondaryStyles() noexcept override { + return inactiveFlag; + } + const char *SCI_METHOD GetSubStyleBases() noexcept override { + return styleSubable; + } + int SCI_METHOD NamedStyles() override { + return std::max(subStyles.LastAllocated() + 1, + sizeLexicalClasses) + + inactiveFlag; + } + const char *SCI_METHOD NameOfStyle(int style) override { + if (style >= NamedStyles()) + return ""; + if (style < sizeLexicalClasses) + return lexicalClasses[style].name; + // TODO: inactive and substyles + return ""; + } + const char *SCI_METHOD TagsOfStyle(int style) override { + if (style >= NamedStyles()) + return "Excess"; + returnBuffer.clear(); + const int firstSubStyle = subStyles.FirstAllocated(); + if (firstSubStyle >= 0) { + const int lastSubStyle = subStyles.LastAllocated(); + if (((style >= firstSubStyle) && (style <= (lastSubStyle))) || + ((style >= firstSubStyle + inactiveFlag) && (style <= (lastSubStyle + inactiveFlag)))) { + int styleActive = style; + if (style > lastSubStyle) { + returnBuffer = "inactive "; + styleActive -= inactiveFlag; + } + const int styleMain = StyleFromSubStyle(styleActive); + returnBuffer += lexicalClasses[styleMain].tags; + return returnBuffer.c_str(); + } + } + if (style < sizeLexicalClasses) + return lexicalClasses[style].tags; + if (style >= inactiveFlag) { + returnBuffer = "inactive "; + const int styleActive = style - inactiveFlag; + if (styleActive < sizeLexicalClasses) + returnBuffer += lexicalClasses[styleActive].tags; + else + returnBuffer.clear(); + return returnBuffer.c_str(); + } + return ""; + } + const char *SCI_METHOD DescriptionOfStyle(int style) override { + if (style >= NamedStyles()) + return ""; + if (style < sizeLexicalClasses) + return lexicalClasses[style].description; + // TODO: inactive and substyles + return ""; + } + + // ILexer5 methods + const char *SCI_METHOD GetName() override { + return caseSensitive ? "cpp" : "cppnocase"; + } + int SCI_METHOD GetIdentifier() override { + return caseSensitive ? SCLEX_CPP : SCLEX_CPPNOCASE; + } + const char *SCI_METHOD PropertyGet(const char *key) override; + + static ILexer5 *LexerFactoryCPP() { + return new LexerCPP(true); + } + static ILexer5 *LexerFactoryCPPInsensitive() { + return new LexerCPP(false); + } + constexpr static int MaskActive(int style) noexcept { + return style & ~inactiveFlag; + } + void EvaluateTokens(Tokens &tokens, const SymbolTable &preprocessorDefinitions); + [[nodiscard]] Tokens Tokenize(const std::string &expr) const; + bool EvaluateExpression(const std::string &expr, const SymbolTable &preprocessorDefinitions); +}; + +Sci_Position SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val) { + if (osCPP.PropertySet(&options, key, val)) { + if (strcmp(key, "lexer.cpp.allow.dollars") == 0) { + setWord = CharacterSet(CharacterSet::setAlphaNum, "._", true); + if (options.identifiersAllowDollars) { + setWord.Add('$'); + } + } + return 0; + } + return -1; +} + +const char *SCI_METHOD LexerCPP::PropertyGet(const char *key) { + return osCPP.PropertyGet(key); +} + +Sci_Position SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &ppDefinitions; + break; + case 5: + wordListN = &markerList; + break; + default: + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + if (wordListN->Set(wl)) { + firstModification = 0; + if (n == 4) { + // Rebuild preprocessorDefinitions + preprocessorDefinitionsStart.clear(); + for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) { + const Definition def = ParseDefine(ppDefinitions.WordAt(nDefinition), "(="); + preprocessorDefinitionsStart[std::string(def.name)] = SymbolValue(def.value, def.arguments); + } + } + } + } + return firstModification; +} + +void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + const StyleContext::Transform transform = caseSensitive ? + StyleContext::Transform::none : StyleContext::Transform::lower; + + const CharacterSet setOKBeforeRE("([{=,:;!%^&*|?~+-> "); + const CharacterSet setCouldBePostOp("+-"); + + const CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + setWordStart = CharacterSet(CharacterSet::setAlpha, "_", true); + + const CharacterSet setInvalidRawFirst(" )\\\t\v\f\n"); + + if (options.identifiersAllowDollars) { + setWordStart.Add('$'); + } + + int chPrevNonWhite = ' '; + int visibleChars = 0; + bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_C_DEFAULT; + int styleBeforeTaskMarker = SCE_C_DEFAULT; + bool continuationLine = false; + bool isIncludePreprocessor = false; + bool isStringInPreprocessor = false; + bool inRERange = false; + bool seenDocKeyBrace = false; + + std::vector interpolatingStack; + + Sci_Position lineCurrent = styler.GetLine(startPos); + if (options.backQuotedStrings == BackQuotedString::TemplateLiteral) { + // code copied from LexPython + auto it = interpolatingAtEol.find(lineCurrent - 1); + if (it != interpolatingAtEol.end()) { + interpolatingStack = it->second; + } + it = interpolatingAtEol.lower_bound(lineCurrent); + if (it != interpolatingAtEol.end()) { + interpolatingAtEol.erase(it, interpolatingAtEol.end()); + } + } + + if ((MaskActive(initStyle) == SCE_C_PREPROCESSOR) || + (MaskActive(initStyle) == SCE_C_COMMENTLINE) || + (MaskActive(initStyle) == SCE_C_COMMENTLINEDOC)) { + // Set continuationLine if last character of previous line is '\' + if (lineCurrent > 0) { + const Sci_Position endLinePrevious = styler.LineEnd(lineCurrent - 1); + if (endLinePrevious > 0) { + continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\'; + } + } + } + + // look back to set chPrevNonWhite properly for better regex colouring + if (startPos > 0) { + Sci_Position back = startPos; + while (--back && IsSpaceEquiv(MaskActive(styler.StyleAt(back)))) + ; + if (MaskActive(styler.StyleAt(back)) == SCE_C_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + } + + StyleContext sc(startPos, length, initStyle, styler); + LinePPState preproc = vlls.ForLine(lineCurrent); + + bool definitionsChanged = false; + + // Truncate ppDefineHistory before current line + + if (!options.updatePreprocessor) + ppDefineHistory.clear(); + + const std::vector::iterator itInvalid = std::find_if( + ppDefineHistory.begin(), ppDefineHistory.end(), + [lineCurrent](const PPDefinition &p) noexcept { return p.line >= lineCurrent; }); + if (itInvalid != ppDefineHistory.end()) { + ppDefineHistory.erase(itInvalid, ppDefineHistory.end()); + definitionsChanged = true; + } + + SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart; + for (const PPDefinition &ppDef : ppDefineHistory) { + if (ppDef.isUndef) + preprocessorDefinitions.erase(ppDef.key); + else + preprocessorDefinitions[ppDef.key] = SymbolValue(ppDef.value, ppDef.arguments); + } + + std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1); + SparseState rawSTNew(lineCurrent); + + std::string currentText; + + int activitySet = preproc.ActiveState(); + + const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER); + const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD); + + Sci_PositionU lineEndNext = styler.LineEnd(lineCurrent); + + if (sc.currentPos == 0 && sc.Match('#', '!')) { + // Shell Shebang at beginning of file + sc.SetState(SCE_C_COMMENTLINE); + sc.Forward(); + } + + for (; sc.More();) { + + if (sc.atLineStart) { + // Using MaskActive() is not needed in the following statement. + // Inside inactive preprocessor declaration, state will be reset anyway at the end of this block. + if ((sc.state == SCE_C_STRING) || (sc.state == SCE_C_CHARACTER)) { + // Prevent SCE_C_STRINGEOL from leaking back to previous line which + // ends with a line continuation by locking in the state up to this position. + sc.SetState(sc.state); + } + if ((MaskActive(sc.state) == SCE_C_PREPROCESSOR) && (!continuationLine)) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + // Reset states to beginning of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lastWordWasUUID = false; + isIncludePreprocessor = false; + inRERange = false; + if (preproc.IsInactive()) { + activitySet = inactiveFlag; + sc.SetState(sc.state | activitySet); + } + } + + if (sc.atLineEnd) { + lineCurrent++; + lineEndNext = styler.LineEnd(lineCurrent); + vlls.Add(lineCurrent, preproc); + if (!rawStringTerminator.empty()) { + rawSTNew.Set(lineCurrent-1, rawStringTerminator); + } + if (!interpolatingStack.empty()) { + interpolatingAtEol[sc.currentLine] = interpolatingStack; + } + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if ((sc.currentPos+1) >= lineEndNext) { + lineCurrent++; + lineEndNext = styler.LineEnd(lineCurrent); + vlls.Add(lineCurrent, preproc); + if (!rawStringTerminator.empty()) { + rawSTNew.Set(lineCurrent-1, rawStringTerminator); + } + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + // Even in UTF-8, \r and \n are separate + sc.Forward(); + } + continuationLine = true; + sc.Forward(); + continue; + } + } + + const bool atLineEndBeforeSwitch = sc.atLineEnd; + + // Determine if the current state should terminate. + switch (MaskActive(sc.state)) { + case SCE_C_OPERATOR: + sc.SetState(SCE_C_DEFAULT|activitySet); + break; + case SCE_C_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (sc.ch == '_') { + sc.ChangeState(SCE_C_USERLITERAL|activitySet); + } else if (!(setWord.Contains(sc.ch) + || (sc.ch == '\'') + || (AnyOf(sc.chPrev, 'e', 'E', 'p', 'P') && AnyOf(sc.ch, '+', '-')))) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_USERLITERAL: + if (!(setWord.Contains(sc.ch))) + sc.SetState(SCE_C_DEFAULT|activitySet); + break; + case SCE_C_IDENTIFIER: + if (sc.atLineStart || sc.atLineEnd || !setWord.Contains(sc.ch) || (sc.ch == '.')) { + sc.GetCurrentString(currentText, transform); + if (keywords.InList(currentText)) { + lastWordWasUUID = currentText == "uuid"; + sc.ChangeState(SCE_C_WORD|activitySet); + } else if (keywords2.InList(currentText)) { + sc.ChangeState(SCE_C_WORD2|activitySet); + } else if (keywords4.InList(currentText)) { + sc.ChangeState(SCE_C_GLOBALCLASS|activitySet); + } else { + const int subStyle = classifierIdentifiers.ValueFor(currentText); + if (subStyle >= 0) { + sc.ChangeState(subStyle|activitySet); + } + } + const bool literalString = sc.ch == '\"'; + if (literalString || sc.ch == '\'') { + std::string_view s = currentText; + size_t lenS = s.length(); + const bool raw = literalString && sc.chPrev == 'R' && !setInvalidRawFirst.Contains(sc.chNext); + if (raw) { + s.remove_suffix(1); + lenS--; + } + const bool valid = + (lenS == 0) || + ((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) || + ((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8')); + if (valid) { + if (literalString) { + if (raw) { + // Set the style of the string prefix to SCE_C_STRINGRAW but then change to + // SCE_C_DEFAULT as that allows the raw string start code to run. + sc.ChangeState(SCE_C_STRINGRAW|activitySet); + sc.SetState(SCE_C_DEFAULT|activitySet); + } else { + sc.ChangeState(SCE_C_STRING|activitySet); + } + } else { + sc.ChangeState(SCE_C_CHARACTER|activitySet); + } + } else { + sc.SetState(SCE_C_DEFAULT | activitySet); + } + } else { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_PREPROCESSOR: + if (options.stylingWithinPreprocessor) { + if (IsASpace(sc.ch) || (sc.ch == '(')) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } else if (isStringInPreprocessor && (sc.Match('>') || sc.Match('\"') || sc.atLineEnd)) { + isStringInPreprocessor = false; + } else if (!isStringInPreprocessor) { + if ((isIncludePreprocessor && sc.Match('<')) || sc.Match('\"')) { + isStringInPreprocessor = true; + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { + sc.SetState(SCE_C_PREPROCESSORCOMMENTDOC|activitySet); + } else { + sc.SetState(SCE_C_PREPROCESSORCOMMENT|activitySet); + } + sc.Forward(); // Eat the * + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_PREPROCESSORCOMMENT: + case SCE_C_PREPROCESSORCOMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_PREPROCESSOR|activitySet); + continue; // Without advancing in case of '\'. + } + break; + case SCE_C_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else { + styleBeforeTaskMarker = SCE_C_COMMENT; + highlightTaskMarker(sc, styler, activitySet, markerList, caseSensitive); + } + break; + case SCE_C_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); + } + } else if ((sc.ch == '<' && sc.chNext != '/') + || (sc.ch == '/' && sc.chPrev == '<')) { // XML comment style + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.ForwardSetState(SCE_C_COMMENTDOCKEYWORD | activitySet); + } + break; + case SCE_C_COMMENTLINE: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else { + styleBeforeTaskMarker = SCE_C_COMMENTLINE; + highlightTaskMarker(sc, styler, activitySet, markerList, caseSensitive); + } + break; + case SCE_C_COMMENTLINEDOC: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); + } + } else if ((sc.ch == '<' && sc.chNext != '/') + || (sc.ch == '/' && sc.chPrev == '<')) { // XML comment style + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.ForwardSetState(SCE_C_COMMENTDOCKEYWORD | activitySet); + } + break; + case SCE_C_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + seenDocKeyBrace = false; + } else if (sc.ch == '[' || sc.ch == '{') { + seenDocKeyBrace = true; + } else if (!setDoxygen.Contains(sc.ch) + && !(seenDocKeyBrace && AnyOf(sc.ch, ',', '.'))) { + if (!(IsASpace(sc.ch) || (sc.ch == 0))) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet); + } else { + sc.GetCurrentString(currentText, transform); + assert(!currentText.empty()); + const std::string currentSuffix = currentText.substr(1); + if (!keywords3.InList(currentSuffix) && !keywords3.InList(currentText)) { + const int subStyleCDKW = classifierDocKeyWords.ValueFor(currentSuffix); + if (subStyleCDKW >= 0) { + sc.ChangeState(subStyleCDKW | activitySet); + } else { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR | activitySet); + } + } + } + sc.SetState(styleBeforeDCKeyword|activitySet); + seenDocKeyBrace = false; + } else if (sc.ch == '>') { + sc.GetCurrentString(currentText, transform); + if (!keywords3.InList(currentText)) { + const int subStyleCDKW = classifierDocKeyWords.ValueFor(currentText.substr(1)); + if (subStyleCDKW >= 0) { + sc.ChangeState(subStyleCDKW | activitySet); + } else { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR | activitySet); + } + } + sc.SetState(styleBeforeDCKeyword | activitySet); + seenDocKeyBrace = false; + } + break; + case SCE_C_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL|activitySet); + } else if (isIncludePreprocessor) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + isIncludePreprocessor = false; + } + } else if (sc.ch == '\\') { + if (options.escapeSequence) { + escapeSeq.resetEscapeState(sc.state, sc.chNext); + sc.SetState(SCE_C_ESCAPESEQUENCE|activitySet); + } + sc.Forward(); // Skip all characters after the backslash + } else if (sc.ch == '\"') { + if (sc.chNext == '_') { + sc.ChangeState(SCE_C_USERLITERAL|activitySet); + } else { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_ESCAPESEQUENCE: + escapeSeq.consumeDigit(); + if (escapeSeq.atEscapeEnd(sc.ch)) { + sc.SetState(escapeSeq.outerState); + continue; + } + break; + case SCE_C_HASHQUOTEDSTRING: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_STRINGRAW: + if (sc.Match(rawStringTerminator.c_str())) { + for (size_t termPos=rawStringTerminator.size(); termPos; termPos--) + sc.Forward(); + sc.SetState(SCE_C_DEFAULT|activitySet); + if (interpolatingStack.empty()) { + rawStringTerminator.clear(); + } + } else if (options.backQuotedStrings == BackQuotedString::TemplateLiteral) { + if (sc.ch == '\\') { + if (options.escapeSequence) { + escapeSeq.resetEscapeState(sc.state, sc.chNext); + sc.SetState(SCE_C_ESCAPESEQUENCE|activitySet); + } + sc.Forward(); // Skip all characters after the backslash + } else if (sc.Match('$', '{')) { + interpolatingStack.push_back({sc.state, 1}); + sc.SetState(SCE_C_OPERATOR|activitySet); + sc.Forward(); + } + } + break; + case SCE_C_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL|activitySet); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + if (sc.chNext == '_') { + sc.ChangeState(SCE_C_USERLITERAL|activitySet); + } else { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (!inRERange && sc.ch == '/') { + sc.Forward(); + while (IsLowerCase(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '\\' && ((sc.currentPos+1) < lineEndNext)) { + // Gobble up the escaped character + sc.Forward(); + } else if (sc.ch == '[') { + inRERange = true; + } else if (sc.ch == ']') { + inRERange = false; + } + break; + case SCE_C_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_VERBATIM: + if (options.verbatimStringsAllowEscapes && (sc.ch == '\\')) { + sc.Forward(); // Skip all characters after the backslash + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_TRIPLEVERBATIM: + if (sc.Match(R"(""")")) { + while (sc.Match('"')) { + sc.Forward(); + } + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_UUID: + if (sc.atLineEnd || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_TASKMARKER: + if (IsOperatorOrSpace(sc.ch)) { + sc.SetState(styleBeforeTaskMarker|activitySet); + styleBeforeTaskMarker = SCE_C_DEFAULT; + } + } + + if (sc.atLineEnd && !atLineEndBeforeSwitch) { + // State exit processing consumed characters up to end of line. + lineCurrent++; + lineEndNext = styler.LineEnd(lineCurrent); + vlls.Add(lineCurrent, preproc); + } + + const bool atLineEndBeforeStateEntry = sc.atLineEnd; + + // Determine if a new state should be entered. + if (MaskActive(sc.state) == SCE_C_DEFAULT) { + if (sc.Match('@', '\"')) { + sc.SetState(SCE_C_VERBATIM|activitySet); + sc.Forward(); + } else if (options.triplequotedStrings && sc.Match(R"(""")")) { + sc.SetState(SCE_C_TRIPLEVERBATIM|activitySet); + sc.Forward(2); + } else if (options.hashquotedStrings && sc.Match('#', '\"')) { + sc.SetState(SCE_C_HASHQUOTEDSTRING|activitySet); + sc.Forward(); + } else if ((options.backQuotedStrings != BackQuotedString::None) && sc.Match('`')) { + sc.SetState(SCE_C_STRINGRAW|activitySet); + rawStringTerminator = "`"; + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID|activitySet); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_NUMBER|activitySet); + } + } else if (!sc.atLineEnd && (setWordStart.Contains(sc.ch) || (sc.ch == '@'))) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID|activitySet); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_IDENTIFIER|activitySet); + } + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTDOC|activitySet); + } else { + sc.SetState(SCE_C_COMMENT|activitySet); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTLINEDOC|activitySet); + else + sc.SetState(SCE_C_COMMENTLINE|activitySet); + } else if (sc.ch == '/' + && (setOKBeforeRE.Contains(chPrevNonWhite) + || followsReturnKeyword(sc, styler)) + && (!setCouldBePostOp.Contains(chPrevNonWhite) + || !FollowsPostfixOperator(sc, styler))) { + sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx + inRERange = false; + } else if (sc.ch == '\"') { + if (sc.chPrev == 'R') { + styler.Flush(); + if (MaskActive(styler.StyleAt(sc.currentPos - 1)) == SCE_C_STRINGRAW) { + sc.SetState(SCE_C_STRINGRAW|activitySet); + rawStringTerminator = ")"; + for (Sci_Position termPos = sc.currentPos + 1;; termPos++) { + const char chTerminator = styler.SafeGetCharAt(termPos, '('); + if (chTerminator == '(') + break; + rawStringTerminator += chTerminator; + } + rawStringTerminator += '\"'; + } else { + sc.SetState(SCE_C_STRING|activitySet); + } + } else { + sc.SetState(SCE_C_STRING|activitySet); + } + isIncludePreprocessor = false; // ensure that '>' won't end the string + } else if (isIncludePreprocessor && sc.ch == '<') { + sc.SetState(SCE_C_STRING|activitySet); + } else if (sc.ch == '\'') { + sc.SetState(SCE_C_CHARACTER|activitySet); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_C_PREPROCESSOR|activitySet); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.Match("include")) { + isIncludePreprocessor = true; + } else { + if (options.trackPreprocessor && IsAlphaNumeric(sc.ch)) { + // If #if is nested too deeply (>31 levels) the active/inactive appearance + // will stop reflecting the code. + if (sc.Match("ifdef") || sc.Match("ifndef")) { + const bool isIfDef = sc.Match("ifdef"); + const int startRest = isIfDef ? 5 : 6; + const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + startRest + 1, false); + const bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); + preproc.StartSection(isIfDef == foundDef); + } else if (sc.Match("if")) { + const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true); + const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); + preproc.StartSection(ifGood); + } else if (sc.Match("else")) { + // #else is shown as active if either preceding or following section is active + // as that means that it contributed to the result. + if (preproc.ValidLevel()) { + // If #else has no corresponding #if then take no action as invalid + if (!preproc.CurrentIfTaken()) { + // Inactive, may become active if parent scope active + assert(sc.state == (SCE_C_PREPROCESSOR | inactiveFlag)); + preproc.InvertCurrentLevel(); + activitySet = preproc.ActiveState(); + // If following is active then show "else" as active + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR); + } else if (preproc.IsActive()) { + // Active -> inactive + assert(sc.state == SCE_C_PREPROCESSOR); + preproc.InvertCurrentLevel(); + activitySet = preproc.ActiveState(); + // Continue to show "else" as active as it ends active section. + } + } + } else if (sc.Match("elif")) { + // Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif + // #elif is shown as active if either preceding or following section is active + // as that means that it contributed to the result. + if (preproc.ValidLevel()) { + if (!preproc.CurrentIfTaken()) { + // Inactive, if expression true then may become active if parent scope active + assert(sc.state == (SCE_C_PREPROCESSOR | inactiveFlag)); + // Similar to #if + const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 4, true); + const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); + if (ifGood) { + preproc.InvertCurrentLevel(); + activitySet = preproc.ActiveState(); + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR); + } + } else if (preproc.IsActive()) { + // Active -> inactive + assert(sc.state == SCE_C_PREPROCESSOR); + preproc.InvertCurrentLevel(); + activitySet = preproc.ActiveState(); + // Continue to show "elif" as active as it ends active section. + } + } + } else if (sc.Match("endif")) { + preproc.EndSection(); + activitySet = preproc.ActiveState(); + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } else if (sc.Match("define")) { + if (options.updatePreprocessor && preproc.IsActive()) { + const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); + const Definition def = ParseDefine(restOfLine, "( \t"); + preprocessorDefinitions[std::string(def.name)] = SymbolValue(def.value, def.arguments); + ppDefineHistory.emplace_back(lineCurrent, def.name, def.value, false, def.arguments); + definitionsChanged = true; + } + } else if (sc.Match("undef")) { + if (options.updatePreprocessor && preproc.IsActive()) { + const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, false); + Tokens tokens = Tokenize(restOfLine); + if (!tokens.empty()) { + const std::string key = tokens[0]; + preprocessorDefinitions.erase(key); + ppDefineHistory.emplace_back(lineCurrent, key, "", true, ""); + definitionsChanged = true; + } + } + } + } + } + } else if (isoperator(sc.ch)) { + sc.SetState(SCE_C_OPERATOR|activitySet); + if (!interpolatingStack.empty() && AnyOf(sc.ch, '{', '}')) { + InterpolatingState ¤t = interpolatingStack.back(); + if (sc.ch == '{') { + current.braceCount += 1; + } else { + current.braceCount -= 1; + if (current.braceCount == 0) { + sc.ForwardSetState(current.state); + interpolatingStack.pop_back(); + continue; + } + } + } + } + } + + if (sc.atLineEnd && !atLineEndBeforeStateEntry) { + // State entry processing consumed characters up to end of line. + lineCurrent++; + lineEndNext = styler.LineEnd(lineCurrent); + vlls.Add(lineCurrent, preproc); + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(MaskActive(sc.state))) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + continuationLine = false; + sc.Forward(); + } + const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent); + if (definitionsChanged || rawStringsChanged) + styler.ChangeLexerState(startPos, startPos + length); + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". + +void SCI_METHOD LexerCPP::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + const Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + bool inLineComment = false; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + Sci_PositionU lineStartNext = styler.LineStart(lineCurrent+1); + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = MaskActive(styler.StyleAt(startPos)); + int style = MaskActive(initStyle); + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (Sci_PositionU i = startPos; i < endPos; i++) { + const char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + const int stylePrev = style; + style = styleNext; + styleNext = MaskActive(styler.StyleAt(i + 1)); + const bool atEOL = i == (lineStartNext-1); + if ((style == SCE_C_COMMENTLINE) || (style == SCE_C_COMMENTLINEDOC)) + inLineComment = true; + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style) && !inLineComment) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_C_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if ((ch == '/') && (chNext == '/')) { + const char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + } + if (options.foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '#') { + Sci_PositionU j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelNext++; + } else if (styler.Match(j, "end")) { + levelNext--; + } + + if (options.foldPreprocessorAtElse && (styler.Match(j, "else") || styler.Match(j, "elif"))) { + levelMinCurrent--; + } + } + } + if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) { + if (ch == '{' || ch == '[' || ch == '(') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (options.foldAtElse && levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}' || ch == ']' || ch == ')') { + levelNext--; + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + if ((options.foldSyntaxBased && options.foldAtElse) || + (options.foldPreprocessor && options.foldPreprocessorAtElse) + ) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + lineStartNext = styler.LineStart(lineCurrent+1); + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + if (atEOL && (i == static_cast(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + inLineComment = false; + } + } +} + +void LexerCPP::EvaluateTokens(Tokens &tokens, const SymbolTable &preprocessorDefinitions) { + + // Remove whitespace tokens + tokens.erase(std::remove_if(tokens.begin(), tokens.end(), OnlySpaceOrTab), tokens.end()); + + // Evaluate defined statements to either 0 or 1 + for (size_t i=0; (i+1)) + const SymbolTable::const_iterator it = preprocessorDefinitions.find(tokens[i+2]); + if (it != preprocessorDefinitions.end()) { + val = "1"; + } + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 4); + } else { + // Spurious '(' so erase as more likely to result in false + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 2); + } + } else { + // defined + const SymbolTable::const_iterator it = preprocessorDefinitions.find(tokens[i+1]); + if (it != preprocessorDefinitions.end()) { + val = "1"; + } + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 2); + } + tokens[i] = val; + } else { + i++; + } + } + + // Evaluate identifiers + constexpr size_t maxIterations = 100; + size_t iterations = 0; // Limit number of iterations in case there is a recursive macro. + for (size_t i = 0; (isecond.value); + if (it->second.IsMacro()) { + if ((i + 1 < tokens.size()) && (tokens.at(i + 1) == "(")) { + // Create map of argument name to value + const Tokens argumentNames = StringSplit(it->second.arguments, ','); + std::map arguments; + size_t arg = 0; + size_t tok = i+2; + while ((tok < tokens.size()) && (arg < argumentNames.size()) && (tokens.at(tok) != ")")) { + if (tokens.at(tok) != ",") { + arguments[argumentNames.at(arg)] = tokens.at(tok); + arg++; + } + tok++; + } + + // Remove invocation + tokens.erase(tokens.begin() + i, tokens.begin() + tok + 1); + + // Substitute values into macro + macroTokens.erase(std::remove_if(macroTokens.begin(), macroTokens.end(), OnlySpaceOrTab), macroTokens.end()); + + for (size_t iMacro = 0; iMacro < macroTokens.size();) { + if (setWordStart.Contains(macroTokens[iMacro][0])) { + const std::map::const_iterator itFind = + arguments.find(macroTokens[iMacro]); + if (itFind != arguments.end()) { + // TODO: Possible that value will be expression so should insert tokenized form + macroTokens[iMacro] = itFind->second; + } + } + iMacro++; + } + + // Insert results back into tokens + tokens.insert(tokens.begin() + i, macroTokens.begin(), macroTokens.end()); + + } else { + i++; + } + } else { + // Remove invocation + tokens.erase(tokens.begin() + i); + // Insert results back into tokens + tokens.insert(tokens.begin() + i, macroTokens.begin(), macroTokens.end()); + } + } else { + // Identifier not found and value defaults to zero + tokens[i] = "0"; + } + } else { + i++; + } + } + + // Find bracketed subexpressions and recurse on them + BracketPair bracketPair = FindBracketPair(tokens); + while (bracketPair.itBracket != tokens.end()) { + Tokens inBracket(bracketPair.itBracket + 1, bracketPair.itEndBracket); + EvaluateTokens(inBracket, preprocessorDefinitions); + + // The insertion is done before the removal because there were failures with the opposite approach + tokens.insert(bracketPair.itBracket, inBracket.begin(), inBracket.end()); + + // insert invalidated bracketPair. Use a new variable to avoid warning from Coverity. + const BracketPair pairToErase = FindBracketPair(tokens); + tokens.erase(pairToErase.itBracket, pairToErase.itEndBracket + 1); + + bracketPair = FindBracketPair(tokens); + } + + // Evaluate logical negations + for (size_t j=0; (j+1)") + result = valA > valB; + else if (tokens[k+1] == ">=") + result = valA >= valB; + else if (tokens[k+1] == "==") + result = valA == valB; + else if (tokens[k+1] == "!=") + result = valA != valB; + else if (tokens[k+1] == "||") + result = valA || valB; + else if (tokens[k+1] == "&&") + result = valA && valB; + const Tokens::iterator itInsert = + tokens.erase(tokens.begin() + k, tokens.begin() + k + 3); + tokens.insert(itInsert, std::to_string(result)); + } else { + k++; + } + } + } +} + +Tokens LexerCPP::Tokenize(const std::string &expr) const { + // Break into tokens + Tokens tokens; + const char *cp = expr.c_str(); + while (*cp) { + std::string word; + if (setWord.Contains(*cp)) { + // Identifiers and numbers + while (setWord.Contains(*cp)) { + word += *cp; + cp++; + } + } else if (IsASpaceOrTab(*cp)) { + while (IsASpaceOrTab(*cp)) { + word += *cp; + cp++; + } + } else if (setRelOp.Contains(*cp)) { + word += *cp; + cp++; + if (setRelOp.Contains(*cp)) { + word += *cp; + cp++; + } + } else if (setLogicalOp.Contains(*cp)) { + word += *cp; + cp++; + if (setLogicalOp.Contains(*cp)) { + word += *cp; + cp++; + } + } else { + // Should handle strings, characters, and comments here + word += *cp; + cp++; + } + tokens.push_back(word); + } + return tokens; +} + +bool LexerCPP::EvaluateExpression(const std::string &expr, const SymbolTable &preprocessorDefinitions) { + Tokens tokens = Tokenize(expr); + + EvaluateTokens(tokens, preprocessorDefinitions); + + // "0" or "" -> false else true + const bool isFalse = tokens.empty() || + ((tokens.size() == 1) && (tokens[0].empty() || tokens[0] == "0")); + return !isFalse; +} + +extern const LexerModule lmCPP(SCLEX_CPP, LexerCPP::LexerFactoryCPP, "cpp", cppWordLists); +extern const LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, LexerCPP::LexerFactoryCPPInsensitive, "cppnocase", cppWordLists); diff --git a/src/lexilla/lexers/LexCSS.cxx b/src/lexilla/lexers/LexCSS.cxx new file mode 100644 index 000000000..76ae62c83 --- /dev/null +++ b/src/lexilla/lexers/LexCSS.cxx @@ -0,0 +1,570 @@ +// Scintilla source code edit control +// Encoding: UTF-8 +/** @file LexCSS.cxx + ** Lexer for Cascading Style Sheets + ** Written by Jakub Vrána + ** Improved by Philippe Lhoste (CSS2) + ** Improved by Ross McKay (SCSS mode; see http://sass-lang.com/ ) + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// TODO: handle SCSS nested properties like font: { weight: bold; size: 1em; } +// TODO: handle SCSS interpolation: #{} +// TODO: add features for Less if somebody feels like contributing; http://lesscss.org/ +// TODO: refactor this monster so that the next poor slob can read it! + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + + +static inline bool IsAWordChar(const unsigned int ch) { + /* FIXME: + * The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars. + * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee + * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher + */ + return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; +} + +inline bool IsCssOperator(const int ch) { + if (!((ch < 0x80) && isalnum(ch)) && + (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || + ch == '.' || ch == '#' || ch == '!' || ch == '@' || + /* CSS2 */ + ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' || + ch == '[' || ch == ']' || ch == '(' || ch == ')')) { + return true; + } + return false; +} + +// look behind (from start of document to our start position) to determine current nesting level +inline int NestingLevelLookBehind(Sci_PositionU startPos, Accessor &styler) { + int ch; + int nestingLevel = 0; + + for (Sci_PositionU i = 0; i < startPos; i++) { + ch = styler.SafeGetCharAt(i); + if (ch == '{') + nestingLevel++; + else if (ch == '}') + nestingLevel--; + } + + return nestingLevel; +} + +static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], Accessor &styler) { + WordList &css1Props = *keywordlists[0]; + WordList &pseudoClasses = *keywordlists[1]; + WordList &css2Props = *keywordlists[2]; + WordList &css3Props = *keywordlists[3]; + WordList &pseudoElements = *keywordlists[4]; + WordList &exProps = *keywordlists[5]; + WordList &exPseudoClasses = *keywordlists[6]; + WordList &exPseudoElements = *keywordlists[7]; + + StyleContext sc(startPos, length, initStyle, styler); + + int lastState = -1; // before operator + int lastStateC = -1; // before comment + int lastStateS = -1; // before single-quoted/double-quoted string + int lastStateVar = -1; // before variable (SCSS) + int lastStateVal = -1; // before value (SCSS) + int op = ' '; // last operator + int opPrev = ' '; // last operator + bool insideParentheses = false; // true if currently in a CSS url() or similar construct + + // property lexer.css.scss.language + // Set to 1 for Sassy CSS (.scss) + bool isScssDocument = styler.GetPropertyInt("lexer.css.scss.language") != 0; + + // property lexer.css.less.language + // Set to 1 for Less CSS (.less) + bool isLessDocument = styler.GetPropertyInt("lexer.css.less.language") != 0; + + // property lexer.css.hss.language + // Set to 1 for HSS (.hss) + bool isHssDocument = styler.GetPropertyInt("lexer.css.hss.language") != 0; + + // SCSS/LESS/HSS have the concept of variable + bool hasVariables = isScssDocument || isLessDocument || isHssDocument; + char varPrefix = 0; + if (hasVariables) + varPrefix = isLessDocument ? '@' : '$'; + + // SCSS/LESS/HSS support single-line comments + typedef enum _CommentModes { eCommentBlock = 0, eCommentLine = 1} CommentMode; + CommentMode comment_mode = eCommentBlock; + bool hasSingleLineComments = isScssDocument || isLessDocument || isHssDocument; + + // must keep track of nesting level in document types that support it (SCSS/LESS/HSS) + bool hasNesting = false; + int nestingLevel = 0; + if (isScssDocument || isLessDocument || isHssDocument) { + hasNesting = true; + nestingLevel = NestingLevelLookBehind(startPos, styler); + } + + // "the loop" + for (; sc.More(); sc.Forward()) { + if (sc.state == SCE_CSS_COMMENT && ((comment_mode == eCommentBlock && sc.Match('*', '/')) || (comment_mode == eCommentLine && sc.atLineEnd))) { + if (lastStateC == -1) { + // backtrack to get last state: + // comments are like whitespace, so we must return to the previous state + Sci_PositionU i = startPos; + for (; i > 0; i--) { + if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) { + if (lastStateC == SCE_CSS_OPERATOR) { + op = styler.SafeGetCharAt(i-1); + opPrev = styler.SafeGetCharAt(i-2); + while (--i) { + lastState = styler.StyleAt(i-1); + if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) + break; + } + if (i == 0) + lastState = SCE_CSS_DEFAULT; + } + break; + } + } + if (i == 0) + lastStateC = SCE_CSS_DEFAULT; + } + if (comment_mode == eCommentBlock) { + sc.Forward(); + sc.ForwardSetState(lastStateC); + } else /* eCommentLine */ { + sc.SetState(lastStateC); + } + } + + if (sc.state == SCE_CSS_COMMENT) + continue; + + if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) { + if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\'')) + continue; + Sci_PositionU i = sc.currentPos; + while (i && styler[i-1] == '\\') + i--; + if ((sc.currentPos - i) % 2 == 1) + continue; + sc.ForwardSetState(lastStateS); + } + + if (sc.state == SCE_CSS_OPERATOR) { + if (op == ' ') { + Sci_PositionU i = startPos; + op = styler.SafeGetCharAt(i-1); + opPrev = styler.SafeGetCharAt(i-2); + while (--i) { + lastState = styler.StyleAt(i-1); + if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) + break; + } + } + switch (op) { + case '@': + if (lastState == SCE_CSS_DEFAULT || hasNesting) + sc.SetState(SCE_CSS_DIRECTIVE); + break; + case '>': + case '+': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_DEFAULT); + break; + case '[': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_ATTRIBUTE); + break; + case ']': + if (lastState == SCE_CSS_ATTRIBUTE) + sc.SetState(SCE_CSS_TAG); + break; + case '{': + nestingLevel++; + switch (lastState) { + case SCE_CSS_GROUP_RULE: + sc.SetState(SCE_CSS_DEFAULT); + break; + case SCE_CSS_TAG: + case SCE_CSS_DIRECTIVE: + sc.SetState(SCE_CSS_IDENTIFIER); + break; + } + break; + case '}': + if (--nestingLevel < 0) + nestingLevel = 0; + switch (lastState) { + case SCE_CSS_DEFAULT: + case SCE_CSS_VALUE: + case SCE_CSS_IMPORTANT: + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + if (hasNesting) + sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); + else + sc.SetState(SCE_CSS_DEFAULT); + break; + } + break; + case '(': + if (lastState == SCE_CSS_PSEUDOCLASS) + sc.SetState(SCE_CSS_TAG); + else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS) + sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS); + break; + case ')': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || + lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) + sc.SetState(SCE_CSS_TAG); + break; + case ':': + switch (lastState) { + case SCE_CSS_TAG: + case SCE_CSS_DEFAULT: + case SCE_CSS_CLASS: + case SCE_CSS_ID: + case SCE_CSS_PSEUDOCLASS: + case SCE_CSS_EXTENDED_PSEUDOCLASS: + case SCE_CSS_UNKNOWN_PSEUDOCLASS: + case SCE_CSS_PSEUDOELEMENT: + case SCE_CSS_EXTENDED_PSEUDOELEMENT: + sc.SetState(SCE_CSS_PSEUDOCLASS); + break; + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + case SCE_CSS_EXTENDED_IDENTIFIER: + case SCE_CSS_UNKNOWN_IDENTIFIER: + case SCE_CSS_VARIABLE: + sc.SetState(SCE_CSS_VALUE); + lastStateVal = lastState; + break; + } + break; + case '.': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_CLASS); + break; + case '#': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_ID); + break; + case ',': + case '|': + case '~': + if (lastState == SCE_CSS_TAG) + sc.SetState(SCE_CSS_DEFAULT); + break; + case ';': + switch (lastState) { + case SCE_CSS_DIRECTIVE: + if (hasNesting) { + sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); + } else { + sc.SetState(SCE_CSS_DEFAULT); + } + break; + case SCE_CSS_VALUE: + case SCE_CSS_IMPORTANT: + // data URLs can have semicolons; simplistically check for wrapping parentheses and move along + if (insideParentheses) { + sc.SetState(lastState); + } else { + if (lastStateVal == SCE_CSS_VARIABLE) { + sc.SetState(SCE_CSS_DEFAULT); + } else { + sc.SetState(SCE_CSS_IDENTIFIER); + } + } + break; + case SCE_CSS_VARIABLE: + if (lastStateVar == SCE_CSS_VALUE) { + // data URLs can have semicolons; simplistically check for wrapping parentheses and move along + if (insideParentheses) { + sc.SetState(SCE_CSS_VALUE); + } else { + sc.SetState(SCE_CSS_IDENTIFIER); + } + } else { + sc.SetState(SCE_CSS_DEFAULT); + } + break; + } + break; + case '!': + if (lastState == SCE_CSS_VALUE) + sc.SetState(SCE_CSS_IMPORTANT); + break; + } + } + + if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) { + sc.SetState(SCE_CSS_TAG); + continue; + } + + // check for inside parentheses (whether part of an "operator" or not) + if (sc.ch == '(') + insideParentheses = true; + else if (sc.ch == ')') + insideParentheses = false; + + // SCSS special modes + if (hasVariables) { + // variable name + if (sc.ch == varPrefix) { + switch (sc.state) { + case SCE_CSS_DEFAULT: + if (isLessDocument) // give priority to pseudo elements + break; + // Falls through. + case SCE_CSS_VALUE: + lastStateVar = sc.state; + sc.SetState(SCE_CSS_VARIABLE); + continue; + } + } + if (sc.state == SCE_CSS_VARIABLE) { + if (IsAWordChar(sc.ch)) { + // still looking at the variable name + continue; + } + if (lastStateVar == SCE_CSS_VALUE) { + // not looking at the variable name any more, and it was part of a value + sc.SetState(SCE_CSS_VALUE); + } + } + + // nested rule parent selector + if (sc.ch == '&') { + switch (sc.state) { + case SCE_CSS_DEFAULT: + case SCE_CSS_IDENTIFIER: + sc.SetState(SCE_CSS_TAG); + continue; + } + } + } + + // nesting rules that apply to SCSS and Less + if (hasNesting) { + // check for nested rule selector + if (sc.state == SCE_CSS_IDENTIFIER && (IsAWordChar(sc.ch) || sc.ch == ':' || sc.ch == '.' || sc.ch == '#')) { + // look ahead to see whether { comes before next ; and } + Sci_PositionU endPos = startPos + length; + int ch; + + for (Sci_PositionU i = sc.currentPos; i < endPos; i++) { + ch = styler.SafeGetCharAt(i); + if (ch == ';' || ch == '}') + break; + if (ch == '{') { + sc.SetState(SCE_CSS_DEFAULT); + continue; + } + } + } + + } + + if (IsAWordChar(sc.ch)) { + if (sc.state == SCE_CSS_DEFAULT) + sc.SetState(SCE_CSS_TAG); + continue; + } + + if (IsAWordChar(sc.chPrev) && ( + sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 || + sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER || + sc.state == SCE_CSS_UNKNOWN_IDENTIFIER || + sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || + sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || + sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || + sc.state == SCE_CSS_IMPORTANT || + sc.state == SCE_CSS_DIRECTIVE + )) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + char *s2 = s; + while (*s2 && !IsAWordChar(*s2)) + s2++; + switch (sc.state) { + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + case SCE_CSS_EXTENDED_IDENTIFIER: + case SCE_CSS_UNKNOWN_IDENTIFIER: + if (css1Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER); + else if (css2Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER2); + else if (css3Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER3); + else if (exProps.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER); + else + sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER); + break; + case SCE_CSS_PSEUDOCLASS: + case SCE_CSS_PSEUDOELEMENT: + case SCE_CSS_EXTENDED_PSEUDOCLASS: + case SCE_CSS_EXTENDED_PSEUDOELEMENT: + case SCE_CSS_UNKNOWN_PSEUDOCLASS: + if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2)) + sc.ChangeState(SCE_CSS_PSEUDOCLASS); + else if (opPrev == ':' && pseudoElements.InList(s2)) + sc.ChangeState(SCE_CSS_PSEUDOELEMENT); + else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS); + else if (opPrev == ':' && exPseudoElements.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT); + else + sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS); + break; + case SCE_CSS_IMPORTANT: + if (strcmp(s2, "important") != 0) + sc.ChangeState(SCE_CSS_VALUE); + break; + case SCE_CSS_DIRECTIVE: + if (op == '@' && (strcmp(s2, "media") == 0 || strcmp(s2, "supports") == 0 || strcmp(s2, "document") == 0 || strcmp(s2, "-moz-document") == 0)) + sc.ChangeState(SCE_CSS_GROUP_RULE); + break; + } + } + + if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && ( + sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID || + (sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */ + sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || + sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || + sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS + )) + )) + sc.SetState(SCE_CSS_TAG); + + if (sc.Match('/', '*')) { + lastStateC = sc.state; + comment_mode = eCommentBlock; + sc.SetState(SCE_CSS_COMMENT); + sc.Forward(); + } else if (hasSingleLineComments && sc.Match('/', '/') && !insideParentheses) { + // note that we've had to treat ([...]// as the start of a URL not a comment, e.g. url(http://example.com), url(//example.com) + lastStateC = sc.state; + comment_mode = eCommentLine; + sc.SetState(SCE_CSS_COMMENT); + sc.Forward(); + } else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE) + && (sc.ch == '\"' || sc.ch == '\'')) { + lastStateS = sc.state; + sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING)); + } else if (IsCssOperator(sc.ch) + && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']') + && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!') + && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_GROUP_RULE) || sc.ch == ';' || sc.ch == '{') + ) { + if (sc.state != SCE_CSS_OPERATOR) + lastState = sc.state; + sc.SetState(SCE_CSS_OPERATOR); + op = sc.ch; + opPrev = sc.chPrev; + } + } + + sc.Complete(); +} + +static void FoldCSSDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT); + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment) { + if (!inComment && (style == SCE_CSS_COMMENT)) + levelCurrent++; + else if (inComment && (style != SCE_CSS_COMMENT)) + levelCurrent--; + inComment = (style == SCE_CSS_COMMENT); + } + if (style == SCE_CSS_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const cssWordListDesc[] = { + "CSS1 Properties", + "Pseudo-classes", + "CSS2 Properties", + "CSS3 Properties", + "Pseudo-elements", + "Browser-Specific CSS Properties", + "Browser-Specific Pseudo-classes", + "Browser-Specific Pseudo-elements", + 0 +}; + +extern const LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc); diff --git a/src/lexilla/lexers/LexCaml.cxx b/src/lexilla/lexers/LexCaml.cxx new file mode 100644 index 000000000..975001f31 --- /dev/null +++ b/src/lexilla/lexers/LexCaml.cxx @@ -0,0 +1,329 @@ +// Scintilla source code edit control +/** @file LexCaml.cxx + ** Lexer for Objective Caml. + **/ +// Copyright 2005-2009 by Robert Roessler +// The License.txt file describes the conditions under which this software may be distributed. +/* Release History + 20050204 Initial release. + 20050205 Quick compiler standards/"cleanliness" adjustment. + 20050206 Added cast for IsLeadByte(). + 20050209 Changes to "external" build support. + 20050306 Fix for 1st-char-in-doc "corner" case. + 20050502 Fix for [harmless] one-past-the-end coloring. + 20050515 Refined numeric token recognition logic. + 20051125 Added 2nd "optional" keywords class. + 20051129 Support "magic" (read-only) comments for RCaml. + 20051204 Swtich to using StyleContext infrastructure. + 20090629 Add full Standard ML '97 support. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wcomma" +#endif + +// Since the Microsoft __iscsym[f] funcs are not ANSI... +inline int iscaml(int c) {return isalnum(c) || c == '_';} +inline int iscamlf(int c) {return isalpha(c) || c == '_';} + +static const int baseT[24] = { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A - L */ + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16 /* M - X */ +}; + +using namespace Lexilla; + +static void ColouriseCamlDoc( + Sci_PositionU startPos, Sci_Position length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) +{ + // initialize styler + StyleContext sc(startPos, length, initStyle, styler); + + Sci_PositionU chToken = 0; + int chBase = 0, chLit = 0; + WordList& keywords = *keywordlists[0]; + WordList& keywords2 = *keywordlists[1]; + WordList& keywords3 = *keywordlists[2]; + const bool isSML = keywords.InList("andalso"); + const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0); + + // set up [initial] state info (terminating states that shouldn't "bleed") + const int state_ = sc.state & 0x0f; + if (state_ <= SCE_CAML_CHAR + || (isSML && state_ == SCE_CAML_STRING)) + sc.state = SCE_CAML_DEFAULT; + int nesting = (state_ >= SCE_CAML_COMMENT)? (state_ - SCE_CAML_COMMENT): 0; + + // foreach char in range... + while (sc.More()) { + // set up [per-char] state info + int state2 = -1; // (ASSUME no state change) + Sci_Position chColor = sc.currentPos - 1;// (ASSUME standard coloring range) + bool advance = true; // (ASSUME scanner "eats" 1 char) + + // step state machine + switch (sc.state & 0x0f) { + case SCE_CAML_DEFAULT: + chToken = sc.currentPos; // save [possible] token start (JIC) + // it's wide open; what do we have? + if (iscamlf(sc.ch)) + state2 = SCE_CAML_IDENTIFIER; + else if (!isSML && sc.Match('`') && iscamlf(sc.chNext)) + state2 = SCE_CAML_TAGNAME; + else if (!isSML && sc.Match('#') && isdigit(sc.chNext)) + state2 = SCE_CAML_LINENUM; + else if (isdigit(sc.ch)) { + // it's a number, assume base 10 + state2 = SCE_CAML_NUMBER, chBase = 10; + if (sc.Match('0')) { + // there MAY be a base specified... + const char* baseC = "bBoOxX"; + if (isSML) { + if (sc.chNext == 'w') + sc.Forward(); // (consume SML "word" indicator) + baseC = "x"; + } + // ... change to specified base AS REQUIRED + if (strchr(baseC, sc.chNext)) + chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward(); + } + } else if (!isSML && sc.Match('\'')) // (Caml char literal?) + state2 = SCE_CAML_CHAR, chLit = 0; + else if (isSML && sc.Match('#', '"')) // (SML char literal?) + state2 = SCE_CAML_CHAR, sc.Forward(); + else if (sc.Match('"')) + state2 = SCE_CAML_STRING; + else if (sc.Match('(', '*')) + state2 = SCE_CAML_COMMENT, sc.Forward(), sc.ch = ' '; // (*)... + else if (strchr("!?~" /* Caml "prefix-symbol" */ + "=<>@^|&+-*/$%" /* Caml "infix-symbol" */ + "()[]{};,:.#", sc.ch) // Caml "bracket" or ;,:.# + // SML "extra" ident chars + || (isSML && (sc.Match('\\') || sc.Match('`')))) + state2 = SCE_CAML_OPERATOR; + break; + + case SCE_CAML_IDENTIFIER: + // [try to] interpret as [additional] identifier char + if (!(iscaml(sc.ch) || sc.Match('\''))) { + const Sci_Position n = sc.currentPos - chToken; + if (n < 24) { + // length is believable as keyword, [re-]construct token + char t[24]; + for (Sci_Position i = -n; i < 0; i++) + t[n + i] = static_cast(sc.GetRelative(i)); + t[n] = '\0'; + // special-case "_" token as KEYWORD + if ((n == 1 && sc.chPrev == '_') || keywords.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD); + else if (keywords2.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD2); + else if (keywords3.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD3); + } + state2 = SCE_CAML_DEFAULT, advance = false; + } + break; + + case SCE_CAML_TAGNAME: + // [try to] interpret as [additional] tagname char + if (!(iscaml(sc.ch) || sc.Match('\''))) + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + /*case SCE_CAML_KEYWORD: + case SCE_CAML_KEYWORD2: + case SCE_CAML_KEYWORD3: + // [try to] interpret as [additional] keyword char + if (!iscaml(ch)) + state2 = SCE_CAML_DEFAULT, advance = false; + break;*/ + + case SCE_CAML_LINENUM: + // [try to] interpret as [additional] linenum directive char + if (!isdigit(sc.ch)) + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + case SCE_CAML_OPERATOR: { + // [try to] interpret as [additional] operator char + const char* o = 0; + if (iscaml(sc.ch) || isspace(sc.ch) // ident or whitespace + || (o = strchr(")]};,\'\"#", sc.ch),o) // "termination" chars + || (!isSML && sc.Match('`')) // Caml extra term char + || (!strchr("!$%&*+-./:<=>?@^|~", sc.ch)// "operator" chars + // SML extra ident chars + && !(isSML && (sc.Match('\\') || sc.Match('`'))))) { + // check for INCLUSIVE termination + if (o && strchr(")]};,", sc.ch)) { + if ((sc.Match(')') && sc.chPrev == '(') + || (sc.Match(']') && sc.chPrev == '[')) + // special-case "()" and "[]" tokens as KEYWORDS + sc.ChangeState(SCE_CAML_KEYWORD); + chColor++; + } else + advance = false; + state2 = SCE_CAML_DEFAULT; + } + break; + } + + case SCE_CAML_NUMBER: + // [try to] interpret as [additional] numeric literal char + if ((!isSML && sc.Match('_')) || IsADigit(sc.ch, chBase)) + break; + // how about an integer suffix? + if (!isSML && (sc.Match('l') || sc.Match('L') || sc.Match('n')) + && (sc.chPrev == '_' || IsADigit(sc.chPrev, chBase))) + break; + // or a floating-point literal? + if (chBase == 10) { + // with a decimal point? + if (sc.Match('.') + && ((!isSML && sc.chPrev == '_') + || IsADigit(sc.chPrev, chBase))) + break; + // with an exponent? (I) + if ((sc.Match('e') || sc.Match('E')) + && ((!isSML && (sc.chPrev == '.' || sc.chPrev == '_')) + || IsADigit(sc.chPrev, chBase))) + break; + // with an exponent? (II) + if (((!isSML && (sc.Match('+') || sc.Match('-'))) + || (isSML && sc.Match('~'))) + && (sc.chPrev == 'e' || sc.chPrev == 'E')) + break; + } + // it looks like we have run out of number + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + case SCE_CAML_CHAR: + if (!isSML) { + // [try to] interpret as [additional] char literal char + if (sc.Match('\\')) { + chLit = 1; // (definitely IS a char literal) + if (sc.chPrev == '\\') + sc.ch = ' '; // (...\\') + // should we be terminating - one way or another? + } else if ((sc.Match('\'') && sc.chPrev != '\\') + || sc.atLineEnd) { + state2 = SCE_CAML_DEFAULT; + if (sc.Match('\'')) + chColor++; + else + sc.ChangeState(SCE_CAML_IDENTIFIER); + // ... maybe a char literal, maybe not + } else if (chLit < 1 && sc.currentPos - chToken >= 2) + sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false; + break; + }/* else + // fall through for SML char literal (handle like string) */ + // Falls through. + + case SCE_CAML_STRING: + // [try to] interpret as [additional] [SML char/] string literal char + if (isSML && sc.Match('\\') && sc.chPrev != '\\' && isspace(sc.chNext)) + state2 = SCE_CAML_WHITE; + else if (sc.Match('\\') && sc.chPrev == '\\') + sc.ch = ' '; // (...\\") + // should we be terminating - one way or another? + else if ((sc.Match('"') && sc.chPrev != '\\') + || (isSML && sc.atLineEnd)) { + state2 = SCE_CAML_DEFAULT; + if (sc.Match('"')) + chColor++; + } + break; + + case SCE_CAML_WHITE: + // [try to] interpret as [additional] SML embedded whitespace char + if (sc.Match('\\')) { + // style this puppy NOW... + state2 = SCE_CAML_STRING, sc.ch = ' ' /* (...\") */, chColor++, + styler.ColourTo(chColor, SCE_CAML_WHITE), styler.Flush(); + // ... then backtrack to determine original SML literal type + Sci_Position p = chColor - 2; + for (; p >= 0 && styler.StyleAt(p) == SCE_CAML_WHITE; p--) ; + if (p >= 0) + state2 = static_cast(styler.StyleAt(p)); + // take care of state change NOW + sc.ChangeState(state2), state2 = -1; + } + break; + + case SCE_CAML_COMMENT: + case SCE_CAML_COMMENT1: + case SCE_CAML_COMMENT2: + case SCE_CAML_COMMENT3: + // we're IN a comment - does this start a NESTED comment? + if (sc.Match('(', '*')) + state2 = sc.state + 1, chToken = sc.currentPos, + sc.Forward(), sc.ch = ' ' /* (*)... */, nesting++; + // [try to] interpret as [additional] comment char + else if (sc.Match(')') && sc.chPrev == '*') { + if (nesting) + state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--; + else + state2 = SCE_CAML_DEFAULT; + chColor++; + // enable "magic" (read-only) comment AS REQUIRED + } else if (useMagic && sc.currentPos - chToken == 4 + && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@') + sc.state |= 0x10; // (switch to read-only comment style) + break; + } + + // handle state change and char coloring AS REQUIRED + if (state2 >= 0) + styler.ColourTo(chColor, sc.state), sc.ChangeState(state2); + // move to next char UNLESS re-scanning current char + if (advance) + sc.Forward(); + } + + // do any required terminal char coloring (JIC) + sc.Complete(); +} + +static +void FoldCamlDoc( + Sci_PositionU, Sci_Position, + int, + WordList *[], + Accessor &) +{ +} + +static const char * const camlWordListDesc[] = { + "Keywords", // primary Objective Caml keywords + "Keywords2", // "optional" keywords (typically from Pervasives) + "Keywords3", // "optional" keywords (typically typenames) + 0 +}; + +extern const LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc); diff --git a/src/lexilla/lexers/LexCmake.cxx b/src/lexilla/lexers/LexCmake.cxx new file mode 100644 index 000000000..0c0a2310a --- /dev/null +++ b/src/lexilla/lexers/LexCmake.cxx @@ -0,0 +1,459 @@ +// Scintilla source code edit control +/** @file LexCmake.cxx + ** Lexer for Cmake + **/ +// Copyright 2007 by Cristian Adam +// based on the NSIS lexer +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static bool isCmakeNumber(char ch) +{ + return(ch >= '0' && ch <= '9'); +} + +static bool isCmakeChar(char ch) +{ + return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isCmakeLetter(char ch) +{ + return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool CmakeNextLineHasElse(Sci_PositionU start, Sci_PositionU end, Accessor &styler) +{ + Sci_Position nNextLine = -1; + for ( Sci_PositionU i = start; i < end; i++ ) { + char cNext = styler.SafeGetCharAt( i ); + if ( cNext == '\n' ) { + nNextLine = i+1; + break; + } + } + + if ( nNextLine == -1 ) // We never foudn the next line... + return false; + + for ( Sci_PositionU firstChar = nNextLine; firstChar < end; firstChar++ ) { + char cNext = styler.SafeGetCharAt( firstChar ); + if ( cNext == ' ' ) + continue; + if ( cNext == '\t' ) + continue; + if ( styler.Match(firstChar, "ELSE") || styler.Match(firstChar, "else")) + return true; + break; + } + + return false; +} + +static int calculateFoldCmake(Sci_PositionU start, Sci_PositionU end, int foldlevel, Accessor &styler, bool bElse) +{ + // If the word is too long, it is not what we are looking for + if ( end - start > 20 ) + return foldlevel; + + int newFoldlevel = foldlevel; + + char s[20]; // The key word we are looking for has atmost 13 characters + for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) { + s[i] = static_cast( styler[ start + i ] ); + s[i + 1] = '\0'; + } + + if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0 + || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0 + || CompareCaseInsensitive(s, "FUNCTION") == 0) + newFoldlevel++; + else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0 + || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0 + || CompareCaseInsensitive(s, "ENDFUNCTION") == 0) + newFoldlevel--; + else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 ) + newFoldlevel++; + else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 ) + newFoldlevel++; + + return newFoldlevel; +} + +static int classifyWordCmake(Sci_PositionU start, Sci_PositionU end, WordList *keywordLists[], Accessor &styler ) +{ + char word[100] = {0}; + char lowercaseWord[100] = {0}; + + WordList &Commands = *keywordLists[0]; + WordList &Parameters = *keywordLists[1]; + WordList &UserDefined = *keywordLists[2]; + + for (Sci_PositionU i = 0; i < end - start + 1 && i < 99; i++) { + word[i] = static_cast( styler[ start + i ] ); + lowercaseWord[i] = static_cast(tolower(word[i])); + } + + // Check for special words... + if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 ) + return SCE_CMAKE_MACRODEF; + + if ( CompareCaseInsensitive(word, "IF") == 0 || CompareCaseInsensitive(word, "ENDIF") == 0 ) + return SCE_CMAKE_IFDEFINEDEF; + + if ( CompareCaseInsensitive(word, "ELSEIF") == 0 || CompareCaseInsensitive(word, "ELSE") == 0 ) + return SCE_CMAKE_IFDEFINEDEF; + + if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0) + return SCE_CMAKE_WHILEDEF; + + if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0) + return SCE_CMAKE_FOREACHDEF; + + if ( Commands.InList(lowercaseWord) ) + return SCE_CMAKE_COMMANDS; + + if ( Parameters.InList(word) ) + return SCE_CMAKE_PARAMETERS; + + + if ( UserDefined.InList(word) ) + return SCE_CMAKE_USERDEFINED; + + if ( strlen(word) > 3 ) { + if ( word[1] == '{' && word[strlen(word)-1] == '}' ) + return SCE_CMAKE_VARIABLE; + } + + // To check for numbers + if ( isCmakeNumber( word[0] ) ) { + bool bHasSimpleCmakeNumber = true; + for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) { + if ( !isCmakeNumber( word[j] ) ) { + bHasSimpleCmakeNumber = false; + break; + } + } + + if ( bHasSimpleCmakeNumber ) + return SCE_CMAKE_NUMBER; + } + + return SCE_CMAKE_DEFAULT; +} + +static void ColouriseCmakeDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_CMAKE_DEFAULT; + if ( startPos > 0 ) + state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox + + styler.StartAt( startPos ); + styler.GetLine( startPos ); + + Sci_PositionU nLengthDoc = startPos + length; + styler.StartSegment( startPos ); + + char cCurrChar; + bool bVarInString = false; + bool bClassicVarInString = false; + + Sci_PositionU i; + for ( i = startPos; i < nLengthDoc; i++ ) { + cCurrChar = styler.SafeGetCharAt( i ); + char cNextChar = styler.SafeGetCharAt(i+1); + + switch (state) { + case SCE_CMAKE_DEFAULT: + if ( cCurrChar == '#' ) { // we have a comment line + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_COMMENT; + break; + } + if ( cCurrChar == '"' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if ( cCurrChar == '\'' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if ( cCurrChar == '`' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + + // CMake Variable + if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) { + styler.ColourTo(i-1,state); + state = SCE_CMAKE_VARIABLE; + + // If it is a number, we must check and set style here first... + if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) + styler.ColourTo( i, SCE_CMAKE_NUMBER); + + break; + } + + break; + case SCE_CMAKE_COMMENT: + if ( cCurrChar == '\n' || cCurrChar == '\r' ) { + if ( styler.SafeGetCharAt(i-1) == '\\' ) { + styler.ColourTo(i-2,state); + styler.ColourTo(i-1,SCE_CMAKE_DEFAULT); + } + else { + styler.ColourTo(i-1,state); + state = SCE_CMAKE_DEFAULT; + } + } + break; + case SCE_CMAKE_STRINGDQ: + case SCE_CMAKE_STRINGLQ: + case SCE_CMAKE_STRINGRQ: + + if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) + break; // Ignore the next character, even if it is a quote of some sort + + if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cNextChar == '\r' || cNextChar == '\n' ) { + Sci_Position nCurLine = styler.GetLine(i+1); + Sci_Position nBack = i; + // We need to check if the previous line has a \ in it... + bool bNextLine = false; + + while ( nBack > 0 ) { + if ( styler.GetLine(nBack) != nCurLine ) + break; + + char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here + + if ( cTemp == '\\' ) { + bNextLine = true; + break; + } + if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) + break; + + nBack--; + } + + if ( bNextLine ) { + styler.ColourTo(i+1,state); + } + if ( bNextLine == false ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + } + } + break; + + case SCE_CMAKE_VARIABLE: + + // CMake Variable: + if ( cCurrChar == '$' ) + state = SCE_CMAKE_DEFAULT; + else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) + state = SCE_CMAKE_DEFAULT; + else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) { + state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler ); + styler.ColourTo( i, state); + state = SCE_CMAKE_DEFAULT; + } + else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) { + if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER ) + styler.ColourTo( i-1, SCE_CMAKE_NUMBER ); + + state = SCE_CMAKE_DEFAULT; + + if ( cCurrChar == '"' ) { + state = SCE_CMAKE_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '`' ) { + state = SCE_CMAKE_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '\'' ) { + state = SCE_CMAKE_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '#' ) { + state = SCE_CMAKE_COMMENT; + } + } + break; + } + + if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) { + bool bIngoreNextDollarSign = false; + + if ( bVarInString && cCurrChar == '$' ) { + bVarInString = false; + bIngoreNextDollarSign = true; + } + else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) { + styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); + bVarInString = false; + bIngoreNextDollarSign = false; + } + + else if ( bVarInString && !isCmakeChar(cNextChar) ) { + int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler); + if ( nWordState == SCE_CMAKE_VARIABLE ) + styler.ColourTo( i, SCE_CMAKE_STRINGVAR); + bVarInString = false; + } + // Covers "${TEST}..." + else if ( bClassicVarInString && cNextChar == '}' ) { + styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); + bClassicVarInString = false; + } + + // Start of var in string + if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) { + styler.ColourTo( i-1, state); + bClassicVarInString = true; + bVarInString = false; + } + else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) { + styler.ColourTo( i-1, state); + bVarInString = true; + bClassicVarInString = false; + } + } + } + + // Colourise remaining document + styler.ColourTo(nLengthDoc-1,state); +} + +static void FoldCmakeDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if ( styler.GetPropertyInt("fold") == 0 ) + return; + + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; + + Sci_Position lineCurrent = styler.GetLine(startPos); + Sci_PositionU safeStartPos = styler.LineStart( lineCurrent ); + + bool bArg1 = true; + Sci_Position nWordStart = -1; + + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + + for (Sci_PositionU i = safeStartPos; i < startPos + length; i++) { + char chCurr = styler.SafeGetCharAt(i); + + if ( bArg1 ) { + if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) { + nWordStart = i; + } + else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) { + int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse); + + if ( newLevel == levelNext ) { + if ( foldAtElse ) { + if ( CmakeNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + } + else + levelNext = newLevel; + bArg1 = false; + } + } + + if ( chCurr == '\n' ) { + if ( bArg1 && foldAtElse) { + if ( CmakeNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + + // If we are on a new line... + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext ) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + levelCurrent = levelNext; + bArg1 = true; // New line, lets look at first argument again + nWordStart = -1; + } + } + + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); +} + +static const char * const cmakeWordLists[] = { + "Commands", + "Parameters", + "UserDefined", + 0, + 0,}; + +extern const LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists); diff --git a/src/lexilla/lexers/LexCoffeeScript.cxx b/src/lexilla/lexers/LexCoffeeScript.cxx new file mode 100644 index 000000000..95f0adb1d --- /dev/null +++ b/src/lexilla/lexers/LexCoffeeScript.cxx @@ -0,0 +1,494 @@ +// Scintilla source code edit control +/** @file LexCoffeeScript.cxx + ** Lexer for CoffeeScript. + **/ +// Copyright 1998-2011 by Neil Hodgson +// Based on the Scintilla C++ Lexer +// Written by Eric Promislow in 2011 for the Komodo IDE +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static bool IsSpaceEquiv(int state) { + return (state == SCE_COFFEESCRIPT_DEFAULT + || state == SCE_COFFEESCRIPT_COMMENTLINE + || state == SCE_COFFEESCRIPT_COMMENTBLOCK + || state == SCE_COFFEESCRIPT_VERBOSE_REGEX + || state == SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT + || state == SCE_COFFEESCRIPT_WORD + || state == SCE_COFFEESCRIPT_REGEX); +} + +// Store the current lexer state and brace count prior to starting a new +// `#{}` interpolation level. +// Based on LexRuby.cxx. +static void enterInnerExpression(int *p_inner_string_types, + int *p_inner_expn_brace_counts, + int& inner_string_count, + int state, + int& brace_counts + ) { + p_inner_string_types[inner_string_count] = state; + p_inner_expn_brace_counts[inner_string_count] = brace_counts; + brace_counts = 0; + ++inner_string_count; +} + +// Restore the lexer state and brace count for the previous `#{}` interpolation +// level upon returning to it. +// Note the previous lexer state is the return value and needs to be restored +// manually by the StyleContext. +// Based on LexRuby.cxx. +static int exitInnerExpression(int *p_inner_string_types, + int *p_inner_expn_brace_counts, + int& inner_string_count, + int& brace_counts + ) { + --inner_string_count; + brace_counts = p_inner_expn_brace_counts[inner_string_count]; + return p_inner_string_types[inner_string_count]; +} + +// Preconditions: sc.currentPos points to a character after '+' or '-'. +// The test for pos reaching 0 should be redundant, +// and is in only for safety measures. +// Limitation: this code will give the incorrect answer for code like +// a = b+++/ptn/... +// Putting a space between the '++' post-inc operator and the '+' binary op +// fixes this, and is highly recommended for readability anyway. +static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) { + Sci_Position pos = (Sci_Position) sc.currentPos; + while (--pos > 0) { + char ch = styler[pos]; + if (ch == '+' || ch == '-') { + return styler[pos - 1] == ch; + } + } + return false; +} + +static bool followsKeyword(StyleContext &sc, Accessor &styler) { + Sci_Position pos = (Sci_Position) sc.currentPos; + Sci_Position currentLine = styler.GetLine(pos); + Sci_Position lineStartPos = styler.LineStart(currentLine); + while (--pos > lineStartPos) { + char ch = styler.SafeGetCharAt(pos); + if (ch != ' ' && ch != '\t') { + break; + } + } + styler.Flush(); + return styler.StyleAt(pos) == SCE_COFFEESCRIPT_WORD; +} + +#if defined(__clang__) +#if __has_warning("-Wunused-but-set-variable") +// Disable warning for visibleChars +#pragma clang diagnostic ignored "-Wunused-but-set-variable" +#endif +#endif + +static void ColouriseCoffeeScriptDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords4 = *keywordlists[3]; + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); + CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); + + CharacterSet setWordStart(CharacterSet::setAlpha, "_$@", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._$", 0x80, true); + + int chPrevNonWhite = ' '; + int visibleChars = 0; + + // String/Regex interpolation variables, based on LexRuby.cxx. + // In most cases a value of 2 should be ample for the code the user is + // likely to enter. For example, + // "Filling the #{container} with #{liquid}..." + // from the CoffeeScript homepage nests to a level of 2 + // If the user actually hits a 6th occurrence of '#{' in a double-quoted + // string (including regexes), it will stay as a string. The problem with + // this is that quotes might flip, a 7th '#{' will look like a comment, + // and code-folding might be wrong. +#define INNER_STRINGS_MAX_COUNT 5 + // These vars track our instances of "...#{,,,'..#{,,,}...',,,}..." + int inner_string_types[INNER_STRINGS_MAX_COUNT]; + // Track # braces when we push a new #{ thing + int inner_expn_brace_counts[INNER_STRINGS_MAX_COUNT]; + int inner_string_count = 0; + int brace_counts = 0; // Number of #{ ... } things within an expression + for (int i = 0; i < INNER_STRINGS_MAX_COUNT; i++) { + inner_string_types[i] = 0; + inner_expn_brace_counts[i] = 0; + } + + // look back to set chPrevNonWhite properly for better regex colouring + Sci_Position endPos = startPos + length; + if (startPos > 0 && IsSpaceEquiv(initStyle)) { + Sci_PositionU back = startPos; + styler.Flush(); + while (back > 0 && IsSpaceEquiv(styler.StyleAt(--back))) + ; + if (styler.StyleAt(back) == SCE_COFFEESCRIPT_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + if (startPos != back) { + initStyle = styler.StyleAt(back); + if (IsSpaceEquiv(initStyle)) { + initStyle = SCE_COFFEESCRIPT_DEFAULT; + } + } + startPos = back; + } + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + for (; sc.More();) { + + if (sc.atLineStart) { + // Reset states to beginning of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_COFFEESCRIPT_OPERATOR: + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + break; + case SCE_COFFEESCRIPT_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!setWord.Contains(sc.ch) || sc.Match('.', '.')) { + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.') || (sc.ch == '$')) { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_COFFEESCRIPT_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_COFFEESCRIPT_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_COFFEESCRIPT_GLOBALCLASS); + } else if (sc.LengthCurrent() > 0 && s[0] == '@') { + sc.ChangeState(SCE_COFFEESCRIPT_INSTANCEPROPERTY); + } + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_WORD: + case SCE_COFFEESCRIPT_WORD2: + case SCE_COFFEESCRIPT_GLOBALCLASS: + case SCE_COFFEESCRIPT_INSTANCEPROPERTY: + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); + } else if (sc.ch == '#' && sc.chNext == '{' && inner_string_count < INNER_STRINGS_MAX_COUNT) { + // process interpolated code #{ ... } + enterInnerExpression(inner_string_types, + inner_expn_brace_counts, + inner_string_count, + sc.state, + brace_counts); + sc.SetState(SCE_COFFEESCRIPT_OPERATOR); + sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_CHARACTER: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + } else if (sc.ch == '/') { + sc.Forward(); + while ((sc.ch < 0x80) && islower(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_COFFEESCRIPT_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_COFFEESCRIPT_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_COMMENTBLOCK: + if (sc.Match("###")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX: + if (sc.Match("///")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT); + } else if (sc.Match('#')) { + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT: + if (sc.atLineStart) { + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_COFFEESCRIPT_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_COFFEESCRIPT_NUMBER); + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_COFFEESCRIPT_IDENTIFIER); + } else if (sc.Match("///")) { + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); + sc.Forward(); + sc.Forward(); + } else if (sc.ch == '/' + && (setOKBeforeRE.Contains(chPrevNonWhite) + || followsKeyword(sc, styler)) + && (!setCouldBePostOp.Contains(chPrevNonWhite) + || !FollowsPostfixOperator(sc, styler))) { + sc.SetState(SCE_COFFEESCRIPT_REGEX); // JavaScript's RegEx + } else if (sc.ch == '\"') { + sc.SetState(SCE_COFFEESCRIPT_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_COFFEESCRIPT_CHARACTER); + } else if (sc.ch == '#') { + if (sc.Match("###")) { + sc.SetState(SCE_COFFEESCRIPT_COMMENTBLOCK); + sc.Forward(); + sc.Forward(); + } else { + sc.SetState(SCE_COFFEESCRIPT_COMMENTLINE); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_COFFEESCRIPT_OPERATOR); + // Handle '..' and '...' operators correctly. + if (sc.ch == '.') { + for (int i = 0; i < 2 && sc.chNext == '.'; i++, sc.Forward()) ; + } else if (sc.ch == '{') { + ++brace_counts; + } else if (sc.ch == '}' && --brace_counts <= 0 && inner_string_count > 0) { + // Return to previous state before #{ ... } + sc.ForwardSetState(exitInnerExpression(inner_string_types, + inner_expn_brace_counts, + inner_string_count, + brace_counts)); + continue; // skip sc.Forward() at loop end + } + } + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + sc.Forward(); + } + sc.Complete(); +} + +static bool IsCommentLine(Sci_Position line, Accessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static void FoldCoffeeScriptDoc(Sci_PositionU startPos, Sci_Position length, int, + WordList *[], Accessor &styler) { + // A simplified version of FoldPyDoc + const Sci_Position maxPos = startPos + length; + const Sci_Position maxLines = styler.GetLine(maxPos - 1); // Requested last line + const Sci_Position docLines = styler.GetLine(styler.Length() - 1); // Available last line + + // property fold.coffeescript.comment + // Set to 1 to allow folding of comment blocks in CoffeeScript. + const bool foldComment = styler.GetPropertyInt("fold.coffeescript.comment") != 0; + + const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + int spaceFlags = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) + && !IsCommentLine(lineCurrent, styler)) + break; + } + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + // Set up initial loop state + int prevComment = 0; + if (lineCurrent >= 1) + prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); + + // Process all characters to end of requested range + // or comment that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of comment at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) { + + // Gather info + int lev = indentCurrent; + Sci_Position lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + const int comment = foldComment && IsCommentLine(lineCurrent, styler); + const int comment_start = (comment && !prevComment && (lineNext <= docLines) && + IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); + const int comment_continue = (comment && prevComment); + if (!comment) + indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + if (comment_start) { + // Place fold point at start of a block of comments + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (comment_continue) { + // Add level to rest of lines in the block + lev = lev + 1; + } + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. + + while ((lineNext < docLines) && + ((indentNext & SC_FOLDLEVELWHITEFLAG) || + (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { + + lineNext++; + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + + const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; + const int levelBeforeComments = std::max(indentCurrentLevel,levelAfterComments); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + Sci_Position skipLine = lineNext; + int skipLevel = levelAfterComments; + + while (--skipLine > lineCurrent) { + int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); + + if (foldCompact) { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) + skipLevel = levelBeforeComments; + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } else { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && + !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && + !IsCommentLine(skipLine, styler)) + skipLevel = levelBeforeComments; + + styler.SetLevel(skipLine, skipLevel); + } + } + + // Set fold header on non-comment line + if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Keep track of block comment state of previous line + prevComment = comment_start || comment_continue; + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, lev); + indentCurrent = indentNext; + lineCurrent = lineNext; + } +} + +static const char *const csWordLists[] = { + "Keywords", + "Secondary keywords", + "Unused", + "Global classes", + 0, +}; + +extern const LexerModule lmCoffeeScript(SCLEX_COFFEESCRIPT, ColouriseCoffeeScriptDoc, "coffeescript", FoldCoffeeScriptDoc, csWordLists); diff --git a/src/lexilla/lexers/LexConf.cxx b/src/lexilla/lexers/LexConf.cxx new file mode 100644 index 000000000..26cc03773 --- /dev/null +++ b/src/lexilla/lexers/LexConf.cxx @@ -0,0 +1,193 @@ +// Scintilla source code edit control +/** @file LexConf.cxx + ** Lexer for Apache Configuration Files. + ** + ** First working version contributed by Ahmad Zawawi on October 28, 2000. + ** i created this lexer because i needed something pretty when dealing + ** when Apache Configuration files... + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static void ColouriseConfDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_CONF_DEFAULT; + char chNext = styler[startPos]; + Sci_Position lengthDoc = startPos + length; + // create a buffer large enough to take the largest chunk... + char *buffer = new char[length+1]; + Sci_Position bufferCount = 0; + + // this assumes that we have 2 keyword list in conf.properties + WordList &directives = *keywordLists[0]; + WordList ¶ms = *keywordLists[1]; + + // go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (Sci_Position i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + switch(state) { + case SCE_CONF_DEFAULT: + if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { + // whitespace is simply ignored here... + styler.ColourTo(i,SCE_CONF_DEFAULT); + break; + } else if( ch == '#' ) { + // signals the start of a comment... + state = SCE_CONF_COMMENT; + styler.ColourTo(i,SCE_CONF_COMMENT); + } else if( ch == '.' /*|| ch == '/'*/) { + // signals the start of a file... + state = SCE_CONF_EXTENSION; + styler.ColourTo(i,SCE_CONF_EXTENSION); + } else if( ch == '"') { + state = SCE_CONF_STRING; + styler.ColourTo(i,SCE_CONF_STRING); + } else if( IsASCII(ch) && ispunct(ch) ) { + // signals an operator... + // no state jump necessary for this + // simple case... + styler.ColourTo(i,SCE_CONF_OPERATOR); + } else if( IsASCII(ch) && isalpha(ch) ) { + // signals the start of an identifier + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + state = SCE_CONF_IDENTIFIER; + } else if( IsASCII(ch) && isdigit(ch) ) { + // signals the start of a number + bufferCount = 0; + buffer[bufferCount++] = ch; + //styler.ColourTo(i,SCE_CONF_NUMBER); + state = SCE_CONF_NUMBER; + } else { + // style it the default style.. + styler.ColourTo(i,SCE_CONF_DEFAULT); + } + break; + + case SCE_CONF_COMMENT: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_CONF_DEFAULT; + } else { + styler.ColourTo(i,SCE_CONF_COMMENT); + } + break; + + case SCE_CONF_EXTENSION: + // if we find a non-alphanumeric char, + // we simply go to default state + // else we're still dealing with an extension... + if( (IsASCII(ch) && isalnum(ch)) || (ch == '_') || + (ch == '-') || (ch == '$') || + (ch == '/') || (ch == '.') || (ch == '*') ) + { + styler.ColourTo(i,SCE_CONF_EXTENSION); + } else { + state = SCE_CONF_DEFAULT; + chNext = styler[i--]; + } + break; + + case SCE_CONF_STRING: + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) { + state = SCE_CONF_DEFAULT; + } + styler.ColourTo(i,SCE_CONF_STRING); + break; + + case SCE_CONF_IDENTIFIER: + // stay in CONF_IDENTIFIER state until we find a non-alphanumeric + if( (IsASCII(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_CONF_DEFAULT; + buffer[bufferCount] = '\0'; + + // check if the buffer contains a keyword, and highlight it if it is a keyword... + if(directives.InList(buffer)) { + styler.ColourTo(i-1,SCE_CONF_DIRECTIVE ); + } else if(params.InList(buffer)) { + styler.ColourTo(i-1,SCE_CONF_PARAMETER ); + } else if(strchr(buffer,'/') || strchr(buffer,'.')) { + styler.ColourTo(i-1,SCE_CONF_EXTENSION); + } else { + styler.ColourTo(i-1,SCE_CONF_DEFAULT); + } + + // push back the faulty character + chNext = styler[i--]; + + } + break; + + case SCE_CONF_NUMBER: + // stay in CONF_NUMBER state until we find a non-numeric + if( (IsASCII(ch) && isdigit(ch)) || ch == '.') { + buffer[bufferCount++] = ch; + } else { + state = SCE_CONF_DEFAULT; + buffer[bufferCount] = '\0'; + + // Colourize here... + if( strchr(buffer,'.') ) { + // it is an IP address... + styler.ColourTo(i-1,SCE_CONF_IP); + } else { + // normal number + styler.ColourTo(i-1,SCE_CONF_NUMBER); + } + + // push back a character + chNext = styler[i--]; + } + break; + + } + } + delete []buffer; +} + +static const char * const confWordListDesc[] = { + "Directives", + "Parameters", + 0 +}; + +extern const LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc); diff --git a/src/lexilla/lexers/LexCrontab.cxx b/src/lexilla/lexers/LexCrontab.cxx new file mode 100644 index 000000000..1a93eee53 --- /dev/null +++ b/src/lexilla/lexers/LexCrontab.cxx @@ -0,0 +1,227 @@ +// Scintilla source code edit control +/** @file LexCrontab.cxx + ** Lexer to use with extended crontab files used by a powerful + ** Windows scheduler/event monitor/automation manager nnCron. + ** (http://nemtsev.eserv.ru/) + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static void ColouriseNncrontabDoc(Sci_PositionU startPos, Sci_Position length, int, WordList +*keywordLists[], Accessor &styler) +{ + int state = SCE_NNCRONTAB_DEFAULT; + char chNext = styler[startPos]; + Sci_Position lengthDoc = startPos + length; + // create a buffer large enough to take the largest chunk... + char *buffer = new char[length+1]; + Sci_Position bufferCount = 0; + // used when highliting environment variables inside quoted string: + bool insideString = false; + + // this assumes that we have 3 keyword list in conf.properties + WordList §ion = *keywordLists[0]; + WordList &keyword = *keywordLists[1]; + WordList &modifier = *keywordLists[2]; + + // go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (Sci_Position i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + switch(state) { + case SCE_NNCRONTAB_DEFAULT: + if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { + // whitespace is simply ignored here... + styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); + break; + } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') { + // signals the start of a task... + state = SCE_NNCRONTAB_TASK; + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } + else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' || + styler.SafeGetCharAt(i+1) == '\t')) { + // signals the start of an extended comment... + state = SCE_NNCRONTAB_COMMENT; + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } else if( ch == '#' ) { + // signals the start of a plain comment... + state = SCE_NNCRONTAB_COMMENT; + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') { + // signals the end of a task... + state = SCE_NNCRONTAB_TASK; + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } else if( ch == '"') { + state = SCE_NNCRONTAB_STRING; + styler.ColourTo(i,SCE_NNCRONTAB_STRING); + } else if( ch == '%') { + // signals environment variables + state = SCE_NNCRONTAB_ENVIRONMENT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') { + // signals environment variables + state = SCE_NNCRONTAB_ENVIRONMENT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + } else if( ch == '*' ) { + // signals an asterisk + // no state jump necessary for this simple case... + styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK); + } else if( (IsASCII(ch) && isalpha(ch)) || ch == '<' ) { + // signals the start of an identifier + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_NNCRONTAB_IDENTIFIER; + } else if( IsASCII(ch) && isdigit(ch) ) { + // signals the start of a number + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_NNCRONTAB_NUMBER; + } else { + // style it the default style.. + styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); + } + break; + + case SCE_NNCRONTAB_COMMENT: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_NNCRONTAB_DEFAULT; + } else { + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } + break; + + case SCE_NNCRONTAB_TASK: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_NNCRONTAB_DEFAULT; + } else { + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } + break; + + case SCE_NNCRONTAB_STRING: + if( ch == '%' ) { + state = SCE_NNCRONTAB_ENVIRONMENT; + insideString = true; + styler.ColourTo(i-1,SCE_NNCRONTAB_STRING); + break; + } + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || + (ch == '\n') || (ch == '\r') ) { + state = SCE_NNCRONTAB_DEFAULT; + } + styler.ColourTo(i,SCE_NNCRONTAB_STRING); + break; + + case SCE_NNCRONTAB_ENVIRONMENT: + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( ch == '%' && insideString ) { + state = SCE_NNCRONTAB_STRING; + insideString = false; + break; + } + if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\') + || (ch == '\n') || (ch == '\r') || (ch == '>') ) { + state = SCE_NNCRONTAB_DEFAULT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + break; + } + styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT); + break; + + case SCE_NNCRONTAB_IDENTIFIER: + // stay in CONF_IDENTIFIER state until we find a non-alphanumeric + if( (IsASCII(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || + (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') || + (ch == '@') ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_NNCRONTAB_DEFAULT; + buffer[bufferCount] = '\0'; + + // check if the buffer contains a keyword, + // and highlight it if it is a keyword... + if(section.InList(buffer)) { + styler.ColourTo(i,SCE_NNCRONTAB_SECTION ); + } else if(keyword.InList(buffer)) { + styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD ); + } // else if(strchr(buffer,'/') || strchr(buffer,'.')) { + // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION); + // } + else if(modifier.InList(buffer)) { + styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER ); + } else { + styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT); + } + // push back the faulty character + chNext = styler[i--]; + } + break; + + case SCE_NNCRONTAB_NUMBER: + // stay in CONF_NUMBER state until we find a non-numeric + if( IsASCII(ch) && isdigit(ch) /* || ch == '.' */ ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_NNCRONTAB_DEFAULT; + buffer[bufferCount] = '\0'; + // Colourize here... (normal number) + styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER); + // push back a character + chNext = styler[i--]; + } + break; + } + } + delete []buffer; +} + +static const char * const cronWordListDesc[] = { + "Section keywords and Forth words", + "nnCrontab keywords", + "Modifiers", + 0 +}; + +extern const LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc); diff --git a/src/lexilla/lexers/LexCsound.cxx b/src/lexilla/lexers/LexCsound.cxx new file mode 100644 index 000000000..d02225931 --- /dev/null +++ b/src/lexilla/lexers/LexCsound.cxx @@ -0,0 +1,215 @@ +// Scintilla source code edit control +/** @file LexCsound.cxx + ** Lexer for Csound (Orchestra & Score) + ** Written by Georg Ritter - + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || + ch == '%' || ch == '@' || ch == '$' || ch == '?'); +} + +static inline bool IsCsoundOperator(char ch) { + if (IsASCII(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '%' || ch == ':') + return true; + return false; +} + +static void ColouriseCsoundDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &opcode = *keywordlists[0]; + WordList &headerStmt = *keywordlists[1]; + WordList &otherKeyword = *keywordlists[2]; + + // Do not leak onto next line + if (initStyle == SCE_CSOUND_STRINGEOL) + initStyle = SCE_CSOUND_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_CSOUND_OPERATOR) { + if (!IsCsoundOperator(static_cast(sc.ch))) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + }else if (sc.state == SCE_CSOUND_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } else if (sc.state == SCE_CSOUND_IDENTIFIER) { + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (opcode.InList(s)) { + sc.ChangeState(SCE_CSOUND_OPCODE); + } else if (headerStmt.InList(s)) { + sc.ChangeState(SCE_CSOUND_HEADERSTMT); + } else if (otherKeyword.InList(s)) { + sc.ChangeState(SCE_CSOUND_USERKEYWORD); + } else if (s[0] == 'p') { + sc.ChangeState(SCE_CSOUND_PARAM); + } else if (s[0] == 'a') { + sc.ChangeState(SCE_CSOUND_ARATE_VAR); + } else if (s[0] == 'k') { + sc.ChangeState(SCE_CSOUND_KRATE_VAR); + } else if (s[0] == 'i') { // covers both i-rate variables and i-statements + sc.ChangeState(SCE_CSOUND_IRATE_VAR); + } else if (s[0] == 'g') { + sc.ChangeState(SCE_CSOUND_GLOBAL_VAR); + } + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + else if (sc.state == SCE_CSOUND_COMMENT ) { + if (sc.atLineEnd) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + else if ((sc.state == SCE_CSOUND_ARATE_VAR) || + (sc.state == SCE_CSOUND_KRATE_VAR) || + (sc.state == SCE_CSOUND_IRATE_VAR)) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_CSOUND_DEFAULT) { + if (sc.ch == ';'){ + sc.SetState(SCE_CSOUND_COMMENT); + } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { + sc.SetState(SCE_CSOUND_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_CSOUND_IDENTIFIER); + } else if (IsCsoundOperator(static_cast(sc.ch))) { + sc.SetState(SCE_CSOUND_OPERATOR); + } else if (sc.ch == 'p') { + sc.SetState(SCE_CSOUND_PARAM); + } else if (sc.ch == 'a') { + sc.SetState(SCE_CSOUND_ARATE_VAR); + } else if (sc.ch == 'k') { + sc.SetState(SCE_CSOUND_KRATE_VAR); + } else if (sc.ch == 'i') { // covers both i-rate variables and i-statements + sc.SetState(SCE_CSOUND_IRATE_VAR); + } else if (sc.ch == 'g') { + sc.SetState(SCE_CSOUND_GLOBAL_VAR); + } + } + } + sc.Complete(); +} + +static void FoldCsoundInstruments(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[], + Accessor &styler) { + Sci_PositionU lengthDoc = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int stylePrev = 0; + int styleNext = styler.StyleAt(startPos); + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) { + char s[20]; + unsigned int j = 0; + while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { + s[j] = styler[i + j]; + j++; + } + s[j] = '\0'; + + if (strcmp(s, "instr") == 0) + levelCurrent++; + if (strcmp(s, "endin") == 0) + levelCurrent--; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + stylePrev = style; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + + +static const char * const csoundWordListDesc[] = { + "Opcodes", + "Header Statements", + "User keywords", + 0 +}; + +extern const LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc); diff --git a/src/lexilla/lexers/LexD.cxx b/src/lexilla/lexers/LexD.cxx new file mode 100644 index 000000000..ba76e6c7e --- /dev/null +++ b/src/lexilla/lexers/LexD.cxx @@ -0,0 +1,571 @@ +/** @file LexD.cxx + ** Lexer for D. + ** + ** Copyright (c) 2006 by Waldemar Augustyn + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +/* Nested comments require keeping the value of the nesting level for every + position in the document. But since scintilla always styles line by line, + we only need to store one value per line. The non-negative number indicates + nesting level at the end of the line. +*/ + +// Underscore, letter, digit and universal alphas from C99 Appendix D. + +static bool IsWordStart(int ch) { + return (IsASCII(ch) && (isalpha(ch) || ch == '_')) || !IsASCII(ch); +} + +static bool IsWord(int ch) { + return (IsASCII(ch) && (isalnum(ch) || ch == '_')) || !IsASCII(ch); +} + +static bool IsDoxygen(int ch) { + if (IsASCII(ch) && islower(ch)) + return true; + if (ch == '$' || ch == '@' || ch == '\\' || + ch == '&' || ch == '#' || ch == '<' || ch == '>' || + ch == '{' || ch == '}' || ch == '[' || ch == ']') + return true; + return false; +} + +static bool IsStringSuffix(int ch) { + return ch == 'c' || ch == 'w' || ch == 'd'; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_D_COMMENT || + style == SCE_D_COMMENTDOC || + style == SCE_D_COMMENTDOCKEYWORD || + style == SCE_D_COMMENTDOCKEYWORDERROR; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerD +struct OptionsD { + bool fold; + bool foldSyntaxBased; + bool foldComment; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + int foldAtElseInt; + bool foldAtElse; + OptionsD() { + fold = false; + foldSyntaxBased = true; + foldComment = false; + foldCommentMultiline = true; + foldCommentExplicit = true; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + foldAtElseInt = -1; + foldAtElse = false; + } +}; + +static const char * const dWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Type definitions and aliases", + "Keywords 5", + "Keywords 6", + "Keywords 7", + 0, + }; + +struct OptionSetD : public OptionSet { + OptionSetD() { + DefineProperty("fold", &OptionsD::fold); + + DefineProperty("fold.d.syntax.based", &OptionsD::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.comment", &OptionsD::foldComment); + + DefineProperty("fold.d.comment.multiline", &OptionsD::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.d.comment.explicit", &OptionsD::foldCommentExplicit, + "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + + DefineProperty("fold.d.explicit.start", &OptionsD::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.d.explicit.end", &OptionsD::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.d.explicit.anywhere", &OptionsD::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsD::foldCompact); + + DefineProperty("lexer.d.fold.at.else", &OptionsD::foldAtElseInt, + "This option enables D folding on a \"} else {\" line of an if statement."); + + DefineProperty("fold.at.else", &OptionsD::foldAtElse); + + DefineWordListSets(dWordLists); + } +}; + +class LexerD : public DefaultLexer { + bool caseSensitive; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList keywords5; + WordList keywords6; + WordList keywords7; + OptionsD options; + OptionSetD osD; +public: + LexerD(bool caseSensitive_) : + DefaultLexer("D", SCLEX_D), + caseSensitive(caseSensitive_) { + } + virtual ~LexerD() { + } + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char * SCI_METHOD PropertyNames() override { + return osD.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osD.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osD.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char *key) override { + return osD.PropertyGet(key); + } + const char * SCI_METHOD DescribeWordListSets() override { + return osD.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + + static ILexer5 *LexerFactoryD() { + return new LexerD(true); + } +}; + +Sci_Position SCI_METHOD LexerD::PropertySet(const char *key, const char *val) { + if (osD.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerD::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &keywords5; + break; + case 5: + wordListN = &keywords6; + break; + case 6: + wordListN = &keywords7; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerD::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + int styleBeforeDCKeyword = SCE_D_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + Sci_Position curLine = styler.GetLine(startPos); + int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0; + bool numFloat = false; // Float literals have '+' and '-' signs + bool numHex = false; + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_D_OPERATOR: + sc.SetState(SCE_D_DEFAULT); + break; + case SCE_D_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (IsASCII(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) { + continue; + } else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) { + // Don't parse 0..2 as number. + numFloat=true; + continue; + } else if ( ( sc.ch == '-' || sc.ch == '+' ) && ( /*sign and*/ + ( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/ + ( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) { /*hex*/ + // Parse exponent sign in float literals: 2e+10 0x2e+10 + continue; + } else { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_IDENTIFIER: + if (!IsWord(sc.ch)) { + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + sc.ChangeState(SCE_D_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_D_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_D_TYPEDEF); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_D_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_D_WORD6); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_D_WORD7); + } + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_D_COMMENTDOC; + sc.SetState(SCE_D_COMMENTDOCKEYWORD); + } + } + break; + case SCE_D_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC; + sc.SetState(SCE_D_COMMENTDOCKEYWORD); + } + } + break; + case SCE_D_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } else if (!IsDoxygen(sc.ch)) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_D_COMMENTNESTED: + if (sc.Match('+', '/')) { + if (curNcLevel > 0) + curNcLevel -= 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.Forward(); + if (curNcLevel == 0) { + sc.ForwardSetState(SCE_D_DEFAULT); + } + } else if (sc.Match('/','+')) { + curNcLevel += 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.Forward(); + } + break; + case SCE_D_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '"') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_D_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + // Char has no suffixes + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGB: + if (sc.ch == '`') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGR: + if (sc.ch == '"') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_D_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_D_NUMBER); + numFloat = sc.ch == '.'; + // Remember hex literal + numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' ); + } else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q') + && sc.chNext == '"' ) { + // Limited support for hex and delimited strings: parse as r"" + sc.SetState(SCE_D_STRINGR); + sc.Forward(); + } else if (IsWordStart(sc.ch) || sc.ch == '$') { + sc.SetState(SCE_D_IDENTIFIER); + } else if (sc.Match('/','+')) { + curNcLevel += 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.SetState(SCE_D_COMMENTNESTED); + sc.Forward(); + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_D_COMMENTDOC); + } else { + sc.SetState(SCE_D_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_D_COMMENTLINEDOC); + else + sc.SetState(SCE_D_COMMENTLINE); + } else if (sc.ch == '"') { + sc.SetState(SCE_D_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_D_CHARACTER); + } else if (sc.ch == '`') { + sc.SetState(SCE_D_STRINGB); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_D_OPERATOR); + if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator + } + } + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". + +void SCI_METHOD LexerD::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + bool foldAtElse = options.foldAtElseInt >= 0 ? options.foldAtElseInt != 0 : options.foldAtElse; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_D_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_D_OPERATOR)) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (atEOL || (i == endPos-1)) { + if (options.foldComment && options.foldCommentMultiline) { // Handle nested comments + int nc; + nc = styler.GetLineState(lineCurrent); + nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; + levelNext += nc; + } + int levelUse = levelCurrent; + if (options.foldSyntaxBased && foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!IsASpace(ch)) + visibleChars++; + } +} + +extern const LexerModule lmD(SCLEX_D, LexerD::LexerFactoryD, "d", dWordLists); diff --git a/src/lexilla/lexers/LexDMAP.cxx b/src/lexilla/lexers/LexDMAP.cxx new file mode 100644 index 000000000..4eecdcb88 --- /dev/null +++ b/src/lexilla/lexers/LexDMAP.cxx @@ -0,0 +1,236 @@ +// Scintilla source code edit control +/** @file LexDMAP.cxx + ** Lexer for MSC Nastran DMAP. + ** Written by Mark Robinson, based on the Fortran lexer by Chuan-jian Shen, Last changed Aug. 2013 + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +/***************************************/ +#include +#include +#include +#include +#include +#include + +#include +#include +/***************************************/ +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +/***************************************/ + +#if defined(__clang__) +#if __has_warning("-Wunused-but-set-variable") +// Disable warning for numNonBlank +#pragma clang diagnostic ignored "-Wunused-but-set-variable" +#endif +#endif + +using namespace Lexilla; + +/***********************************************/ +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%'); +} +/**********************************************/ +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch)); +} +/***************************************/ +static void ColouriseDMAPDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + /***************************************/ + Sci_Position posLineStart = 0, numNonBlank = 0; + Sci_Position endPos = startPos + length; + /***************************************/ + // backtrack to the nearest keyword + while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_DMAP_WORD)) { + startPos--; + } + startPos = styler.LineStart(styler.GetLine(startPos)); + initStyle = styler.StyleAt(startPos - 1); + StyleContext sc(startPos, endPos-startPos, initStyle, styler); + /***************************************/ + for (; sc.More(); sc.Forward()) { + // remember the start position of the line + if (sc.atLineStart) { + posLineStart = sc.currentPos; + numNonBlank = 0; + sc.SetState(SCE_DMAP_DEFAULT); + } + if (!IsASpaceOrTab(sc.ch)) numNonBlank ++; + /***********************************************/ + // Handle data appearing after column 72; it is ignored + Sci_Position toLineStart = sc.currentPos - posLineStart; + if (toLineStart >= 72 || sc.ch == '$') { + sc.SetState(SCE_DMAP_COMMENT); + while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end + continue; + } + /***************************************/ + // Determine if the current state should terminate. + if (sc.state == SCE_DMAP_OPERATOR) { + sc.SetState(SCE_DMAP_DEFAULT); + } else if (sc.state == SCE_DMAP_NUMBER) { + if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) { + sc.SetState(SCE_DMAP_DEFAULT); + } + } else if (sc.state == SCE_DMAP_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '%')) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_DMAP_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_DMAP_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_DMAP_WORD3); + } + sc.SetState(SCE_DMAP_DEFAULT); + } + } else if (sc.state == SCE_DMAP_COMMENT) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_DMAP_DEFAULT); + } + } else if (sc.state == SCE_DMAP_STRING1) { + if (sc.ch == '\'') { + if (sc.chNext == '\'') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_DMAP_DEFAULT); + } + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_DMAP_STRINGEOL); + sc.ForwardSetState(SCE_DMAP_DEFAULT); + } + } else if (sc.state == SCE_DMAP_STRING2) { + if (sc.atLineEnd) { + sc.ChangeState(SCE_DMAP_STRINGEOL); + sc.ForwardSetState(SCE_DMAP_DEFAULT); + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_DMAP_DEFAULT); + } + } + } + /***************************************/ + // Determine if a new state should be entered. + if (sc.state == SCE_DMAP_DEFAULT) { + if (sc.ch == '$') { + sc.SetState(SCE_DMAP_COMMENT); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)) || (sc.ch == '-' && IsADigit(sc.chNext))) { + sc.SetState(SCE_F_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_DMAP_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_DMAP_STRING2); + } else if (sc.ch == '\'') { + sc.SetState(SCE_DMAP_STRING1); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_DMAP_OPERATOR); + } + } + } + sc.Complete(); +} +/***************************************/ +// To determine the folding level depending on keywords +static int classifyFoldPointDMAP(const char* s, const char* prevWord) { + int lev = 0; + if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "enddo") == 0 || strcmp(s, "endif") == 0) { + lev = -1; + } else if ((strcmp(prevWord, "do") == 0 && strcmp(s, "while") == 0) || strcmp(s, "then") == 0) { + lev = 1; + } + return lev; +} +// Folding the code +static void FoldDMAPDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *[], Accessor &styler) { + // + // bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + // Do not know how to fold the comment at the moment. + // + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + /***************************************/ + Sci_Position lastStart = 0; + char prevWord[32] = ""; + /***************************************/ + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + // + if ((stylePrev == SCE_DMAP_DEFAULT || stylePrev == SCE_DMAP_OPERATOR || stylePrev == SCE_DMAP_COMMENT) && (style == SCE_DMAP_WORD)) { + // Store last word and label start point. + lastStart = i; + } + /***************************************/ + if (style == SCE_DMAP_WORD) { + if(iswordchar(ch) && !iswordchar(chNext)) { + char s[32]; + Sci_PositionU k; + for(k=0; (k<31 ) && (k(tolower(styler[lastStart+k])); + } + s[k] = '\0'; + levelCurrent += classifyFoldPointDMAP(s, prevWord); + strcpy(prevWord, s); + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + strcpy(prevWord, ""); + } + /***************************************/ + if (!isspacechar(ch)) visibleChars++; + } + /***************************************/ + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} +/***************************************/ +static const char * const DMAPWordLists[] = { + "Primary keywords and identifiers", + "Intrinsic functions", + "Extended and user defined functions", + 0, +}; +/***************************************/ +extern const LexerModule lmDMAP(SCLEX_DMAP, ColouriseDMAPDoc, "DMAP", FoldDMAPDoc, DMAPWordLists); diff --git a/src/lexilla/lexers/LexDMIS.cxx b/src/lexilla/lexers/LexDMIS.cxx new file mode 100644 index 000000000..60ad5fdd6 --- /dev/null +++ b/src/lexilla/lexers/LexDMIS.cxx @@ -0,0 +1,367 @@ +// Scintilla source code edit control +/** @file LexDMIS.cxx + ** Lexer for DMIS. + **/ +// Copyright 1998-2005 by Neil Hodgson +// Copyright 2013-2014 by Andreas Tscharner +// The License.txt file describes the conditions under which this software may be distributed. + + +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "DefaultLexer.h" + +using namespace Lexilla; + + +static const char *const DMISWordListDesc[] = { + "DMIS Major Words", + "DMIS Minor Words", + "Unsupported DMIS Major Words", + "Unsupported DMIS Minor Words", + "Keywords for code folding start", + "Corresponding keywords for code folding end", + 0 +}; + + +class LexerDMIS : public DefaultLexer +{ + private: + char *m_wordListSets; + WordList m_majorWords; + WordList m_minorWords; + WordList m_unsupportedMajor; + WordList m_unsupportedMinor; + WordList m_codeFoldingStart; + WordList m_codeFoldingEnd; + + char * SCI_METHOD UpperCase(char *item); + void SCI_METHOD InitWordListSets(void); + + public: + LexerDMIS(void); + virtual ~LexerDMIS(void); + + int SCI_METHOD Version() const override { + return Scintilla::lvRelease5; + } + + void SCI_METHOD Release() override { + delete this; + } + + const char * SCI_METHOD PropertyNames() override { + return NULL; + } + + int SCI_METHOD PropertyType(const char *) override { + return -1; + } + + const char * SCI_METHOD DescribeProperty(const char *) override { + return NULL; + } + + Sci_Position SCI_METHOD PropertySet(const char *, const char *) override { + return -1; + } + + const char * SCI_METHOD PropertyGet(const char *) override { + return NULL; + } + + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return NULL; + } + + static ILexer5 *LexerFactoryDMIS() { + return new LexerDMIS; + } + + const char * SCI_METHOD DescribeWordListSets() override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, Scintilla::IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, Scintilla::IDocument *pAccess) override; +}; + + +char * SCI_METHOD LexerDMIS::UpperCase(char *item) +{ + char *itemStart; + + + itemStart = item; + while (item && *item) { + *item = toupper(*item); + item++; + }; + return itemStart; +} + +void SCI_METHOD LexerDMIS::InitWordListSets(void) +{ + size_t totalLen = 0; + + + for (int i=0; DMISWordListDesc[i]; i++) { + totalLen += strlen(DMISWordListDesc[i]); + totalLen++; + }; + + totalLen++; + this->m_wordListSets = new char[totalLen]; + memset(this->m_wordListSets, 0, totalLen); + + for (int i=0; DMISWordListDesc[i]; i++) { + strcat(this->m_wordListSets, DMISWordListDesc[i]); + strcat(this->m_wordListSets, "\n"); + }; +} + + +LexerDMIS::LexerDMIS(void) : DefaultLexer("DMIS", SCLEX_DMIS) { + this->InitWordListSets(); + + this->m_majorWords.Clear(); + this->m_minorWords.Clear(); + this->m_unsupportedMajor.Clear(); + this->m_unsupportedMinor.Clear(); + this->m_codeFoldingStart.Clear(); + this->m_codeFoldingEnd.Clear(); +} + +LexerDMIS::~LexerDMIS(void) { + delete[] this->m_wordListSets; +} + +Sci_Position SCI_METHOD LexerDMIS::WordListSet(int n, const char *wl) +{ + switch (n) { + case 0: + this->m_majorWords.Clear(); + this->m_majorWords.Set(wl); + break; + case 1: + this->m_minorWords.Clear(); + this->m_minorWords.Set(wl); + break; + case 2: + this->m_unsupportedMajor.Clear(); + this->m_unsupportedMajor.Set(wl); + break; + case 3: + this->m_unsupportedMinor.Clear(); + this->m_unsupportedMinor.Set(wl); + break; + case 4: + this->m_codeFoldingStart.Clear(); + this->m_codeFoldingStart.Set(wl); + break; + case 5: + this->m_codeFoldingEnd.Clear(); + this->m_codeFoldingEnd.Set(wl); + break; + default: + return -1; + break; + } + + return 0; +} + +const char * SCI_METHOD LexerDMIS::DescribeWordListSets() +{ + return this->m_wordListSets; +} + +void SCI_METHOD LexerDMIS::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, Scintilla::IDocument *pAccess) +{ + const Sci_PositionU MAX_STR_LEN = 100; + + LexAccessor styler(pAccess); + StyleContext scCTX(startPos, lengthDoc, initStyle, styler); + CharacterSet setDMISNumber(CharacterSet::setDigits, ".-+eE"); + CharacterSet setDMISWordStart(CharacterSet::setAlpha, "-234", 0x80, true); + CharacterSet setDMISWord(CharacterSet::setAlpha); + + + bool isIFLine = false; + + for (; scCTX.More(); scCTX.Forward()) { + if (scCTX.atLineEnd) { + isIFLine = false; + }; + + switch (scCTX.state) { + case SCE_DMIS_DEFAULT: + if (scCTX.Match('$', '$')) { + scCTX.SetState(SCE_DMIS_COMMENT); + scCTX.Forward(); + }; + if (scCTX.Match('\'')) { + scCTX.SetState(SCE_DMIS_STRING); + }; + if (IsADigit(scCTX.ch) || ((scCTX.Match('-') || scCTX.Match('+')) && IsADigit(scCTX.chNext))) { + scCTX.SetState(SCE_DMIS_NUMBER); + break; + }; + if (setDMISWordStart.Contains(scCTX.ch)) { + scCTX.SetState(SCE_DMIS_KEYWORD); + }; + if (scCTX.Match('(') && (!isIFLine)) { + scCTX.SetState(SCE_DMIS_LABEL); + }; + break; + + case SCE_DMIS_COMMENT: + if (scCTX.atLineEnd) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_STRING: + if (scCTX.Match('\'')) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_NUMBER: + if (!setDMISNumber.Contains(scCTX.ch)) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + + case SCE_DMIS_KEYWORD: + if (!setDMISWord.Contains(scCTX.ch)) { + char tmpStr[MAX_STR_LEN]; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + scCTX.GetCurrent(tmpStr, (MAX_STR_LEN-1)); + // The following strncpy is copying from a string back onto itself which is weird and causes warnings + // but is harmless so turn off the warning +#if defined(__GNUC__) && !defined(__clang__) +// Disable warning for strncpy +#pragma GCC diagnostic ignored "-Wrestrict" +#endif + strncpy(tmpStr, this->UpperCase(tmpStr), (MAX_STR_LEN-1)); + + if (this->m_minorWords.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_MINORWORD); + }; + if (this->m_majorWords.InList(tmpStr)) { + isIFLine = (strcmp(tmpStr, "IF") == 0); + scCTX.ChangeState(SCE_DMIS_MAJORWORD); + }; + if (this->m_unsupportedMajor.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MAJOR); + }; + if (this->m_unsupportedMinor.InList(tmpStr)) { + scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MINOR); + }; + + if (scCTX.Match('(') && (!isIFLine)) { + scCTX.SetState(SCE_DMIS_LABEL); + } else { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + }; + break; + + case SCE_DMIS_LABEL: + if (scCTX.Match(')')) { + scCTX.SetState(SCE_DMIS_DEFAULT); + }; + break; + }; + }; + scCTX.Complete(); +} + +void SCI_METHOD LexerDMIS::Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int, Scintilla::IDocument *pAccess) +{ + const int MAX_STR_LEN = 100; + + LexAccessor styler(pAccess); + Sci_PositionU endPos = startPos + lengthDoc; + char chNext = styler[startPos]; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int strPos = 0; + bool foldWordPossible = false; + CharacterSet setDMISFoldWord(CharacterSet::setAlpha); + char *tmpStr; + + + tmpStr = new char[MAX_STR_LEN]; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + + for (Sci_PositionU i=startPos; i= (MAX_STR_LEN-1)) { + strPos = MAX_STR_LEN-1; + }; + + int style = styler.StyleAt(i); + bool noFoldPos = ((style == SCE_DMIS_COMMENT) || (style == SCE_DMIS_STRING)); + + if (foldWordPossible) { + if (setDMISFoldWord.Contains(ch)) { + tmpStr[strPos++] = ch; + } else { + tmpStr = this->UpperCase(tmpStr); + if (this->m_codeFoldingStart.InList(tmpStr) && (!noFoldPos)) { + levelCurrent++; + }; + if (this->m_codeFoldingEnd.InList(tmpStr) && (!noFoldPos)) { + levelCurrent--; + }; + memset(tmpStr, 0, MAX_STR_LEN*sizeof(char)); + strPos = 0; + foldWordPossible = false; + }; + } else { + if (setDMISFoldWord.Contains(ch)) { + tmpStr[strPos++] = ch; + foldWordPossible = true; + }; + }; + + if (atEOL || (i == (endPos-1))) { + int lev = levelPrev; + + if (levelCurrent > levelPrev) { + lev |= SC_FOLDLEVELHEADERFLAG; + }; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + }; + lineCurrent++; + levelPrev = levelCurrent; + }; + }; + delete[] tmpStr; +} + + +extern const LexerModule lmDMIS(SCLEX_DMIS, LexerDMIS::LexerFactoryDMIS, "DMIS", DMISWordListDesc); diff --git a/src/lexilla/lexers/LexDataflex.cxx b/src/lexilla/lexers/LexDataflex.cxx new file mode 100644 index 000000000..67b022d18 --- /dev/null +++ b/src/lexilla/lexers/LexDataflex.cxx @@ -0,0 +1,611 @@ +// Scintilla source code edit control +/** @file LexDataflex.cxx + ** Lexer for DataFlex. + ** Based on LexPascal.cxx + ** Written by Wil van Antwerpen, June 2019 + **/ + +/* +// The License.txt file describes the conditions under which this software may be distributed. + +A few words about features of LexDataflex... + +Generally speaking LexDataflex tries to support all available DataFlex features (up +to DataFlex 19.1 at this time). + +~ FOLDING: + +Folding is supported in the following cases: + +- Folding of stream-like comments +- Folding of groups of consecutive line comments +- Folding of preprocessor blocks (the following preprocessor blocks are +supported: #IFDEF, #IFNDEF, #ENDIF and #HEADER / #ENDHEADER +blocks), +- Folding of code blocks on appropriate keywords (the following code blocks are +supported: "begin, struct, type, case / end" blocks, class & object +declarations and interface declarations) + +Remarks: + +- We pass 4 arrays to the lexer: +1. The DataFlex keyword list, these are normal DataFlex keywords +2. The Scope Open list, for example, begin / procedure / while +3. The Scope Close list, for example, end / end_procedure / loop +4. Operator list, for ex. + / - / * / Lt / iand +These lists are all mutually exclusive, scope open words should not be in the keyword list and vice versa + +- Folding of code blocks tries to handle all special cases in which folding +should not occur. + +~ KEYWORDS: + +The list of keywords that can be used in dataflex.properties file (up to DataFlex +19.1): + +- Keywords: .. snipped .. see dataflex.properties file. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + + +static void GetRangeLowered(Sci_PositionU start, + Sci_PositionU end, + Accessor &styler, + char *s, + Sci_PositionU len) { + Sci_PositionU i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void GetForwardRangeLowered(Sci_PositionU start, + CharacterSet &charSet, + Accessor &styler, + char *s, + Sci_PositionU len) { + Sci_PositionU i = 0; + while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) { + s[i] = static_cast(tolower(styler.SafeGetCharAt(start + i))); + i++; + } + s[i] = '\0'; + +} + +enum { + stateInICode = 0x1000, + stateSingleQuoteOpen = 0x2000, + stateDoubleQuoteOpen = 0x4000, + stateFoldInPreprocessor = 0x0100, + stateFoldInCaseStatement = 0x0200, + stateFoldInPreprocessorLevelMask = 0x00FF, + stateFoldMaskAll = 0x0FFF +}; + + +static bool IsFirstDataFlexWord(Sci_Position pos, Accessor &styler) { + Sci_Position line = styler.GetLine(pos); + Sci_Position start_pos = styler.LineStart(line); + for (Sci_Position i = start_pos; i < pos; i++) { + char ch = styler.SafeGetCharAt(i); + if (!(ch == ' ' || ch == '\t')) + return false; + } + return true; +} + + +inline bool IsADataFlexField(int ch) { + return (ch == '.'); +} + + +static void ClassifyDataFlexWord(WordList *keywordlists[], StyleContext &sc, Accessor &styler) { + WordList& keywords = *keywordlists[0]; + WordList& scopeOpen = *keywordlists[1]; + WordList& scopeClosed = *keywordlists[2]; + WordList& operators = *keywordlists[3]; + + char s[100]; + int oldState; + int newState; + size_t tokenlen; + + oldState = sc.state; + newState = oldState; + sc.GetCurrentLowered(s, sizeof(s)); + tokenlen = strnlen(s,sizeof(s)); + if (keywords.InList(s)) { + // keywords in DataFlex can be used as table column names (file.field) and as such they + // should not be characterized as a keyword. So test for that. + // for ex. somebody using date as field name. + if (!IsADataFlexField(sc.GetRelative(-static_cast(tokenlen+1)))) { + newState = SCE_DF_WORD; + } + } + if (oldState == newState) { + if ((scopeOpen.InList(s) || scopeClosed.InList(s)) && (strcmp(s, "for") != 0) && (strcmp(s, "repeat") != 0)) { + // scope words in DataFlex can be used as table column names (file.field) and as such they + // should not be characterized as a scope word. So test for that. + // for ex. somebody using procedure for field name. + if (!IsADataFlexField(sc.GetRelative(-static_cast(tokenlen+1)))) { + newState = SCE_DF_SCOPEWORD; + } + } + // no code folding on the next words, but just want to paint them like keywords (as they are) (??? doesn't the code to the opposite?) + if (strcmp(s, "if") == 0 || + strcmp(s, "ifnot") == 0 || + strcmp(s, "case") == 0 || + strcmp(s, "else") == 0 ) { + newState = SCE_DF_SCOPEWORD; + } + } + if (oldState != newState && newState == SCE_DF_WORD) { + // a for loop must have for at the start of the line, for is also used in "define abc for 123" + if ( (strcmp(s, "for") == 0) && (IsFirstDataFlexWord(sc.currentPos-3, styler)) ) { + newState = SCE_DF_SCOPEWORD; + } + } + if (oldState != newState && newState == SCE_DF_WORD) { + // a repeat loop must have repeat at the start of the line, repeat is also used in 'move (repeat("d",5)) to sFoo' + if ( (strcmp(s, "repeat") == 0) && (IsFirstDataFlexWord(sc.currentPos-6, styler)) ) { + newState = SCE_DF_SCOPEWORD; + } + } + if (oldState == newState) { + if (operators.InList(s)) { + newState = SCE_DF_OPERATOR; + } + } + + if (oldState != newState) { + sc.ChangeState(newState); + } + sc.SetState(SCE_DF_DEFAULT); +} + +static void ColouriseDataFlexDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { +// bool bSmartHighlighting = styler.GetPropertyInt("lexer.dataflex.smart.highlighting", 1) != 0; + + CharacterSet setWordStart(CharacterSet::setAlpha, "_$#@", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "_$#@", 0x80, true); + CharacterSet setNumber(CharacterSet::setDigits, ".-+eE"); + CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF"); + CharacterSet setOperator(CharacterSet::setNone, "*+-/<=>^"); + + Sci_Position curLine = styler.GetLine(startPos); + int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curLineState); + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_DF_NUMBER: + if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) { + sc.SetState(SCE_DF_DEFAULT); + } else if (sc.ch == '-' || sc.ch == '+') { + if (sc.chPrev != 'E' && sc.chPrev != 'e') { + sc.SetState(SCE_DF_DEFAULT); + } + } + break; + case SCE_DF_IDENTIFIER: + if (!setWord.Contains(sc.ch)) { + ClassifyDataFlexWord(keywordlists, sc, styler); + } + break; + case SCE_DF_HEXNUMBER: + if (!(setHexNumber.Contains(sc.ch) || sc.ch == 'I') ) { // in |CI$22a we also want to color the "I" + sc.SetState(SCE_DF_DEFAULT); + } + break; + case SCE_DF_METATAG: + if (sc.atLineStart || sc.chPrev == '}') { + sc.SetState(SCE_DF_DEFAULT); + } + break; + case SCE_DF_PREPROCESSOR: + if (sc.atLineStart || IsASpaceOrTab(sc.ch)) { + sc.SetState(SCE_DF_DEFAULT); + } + break; + case SCE_DF_IMAGE: + if (sc.atLineStart && sc.Match("/*")) { + sc.Forward(); // these characters are still part of the DF Image + sc.ForwardSetState(SCE_DF_DEFAULT); + } + break; + case SCE_DF_PREPROCESSOR2: + // we don't have inline comments or preprocessor2 commands + //if (sc.Match('*', ')')) { + // sc.Forward(); + // sc.ForwardSetState(SCE_DF_DEFAULT); + //} + break; + case SCE_DF_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_DF_DEFAULT); + } + break; + case SCE_DF_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_DF_STRINGEOL); + } else if (sc.ch == '\'' && sc.chNext == '\'') { + sc.Forward(); + } else if (sc.ch == '\"' && sc.chNext == '\"') { + sc.Forward(); + } else if (sc.ch == '\'' || sc.ch == '\"') { + if (sc.ch == '\'' && (curLineState & stateSingleQuoteOpen) ) { + curLineState &= ~(stateSingleQuoteOpen); + sc.ForwardSetState(SCE_DF_DEFAULT); + } + else if (sc.ch == '\"' && (curLineState & stateDoubleQuoteOpen) ) { + curLineState &= ~(stateDoubleQuoteOpen); + sc.ForwardSetState(SCE_DF_DEFAULT); + } + } + break; + case SCE_DF_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_DF_DEFAULT); + } + break; + case SCE_DF_SCOPEWORD: + //if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') { + // sc.SetState(SCE_DF_DEFAULT); + //} + break; + case SCE_DF_OPERATOR: +// if (bSmartHighlighting && sc.chPrev == ';') { +// curLineState &= ~(stateInProperty | stateInExport); +// } + sc.SetState(SCE_DF_DEFAULT); + break; + case SCE_DF_ICODE: + if (sc.atLineStart || IsASpace(sc.ch) || isoperator(sc.ch)) { + sc.SetState(SCE_DF_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_DF_DEFAULT) { + if (IsADigit(sc.ch)) { + sc.SetState(SCE_DF_NUMBER); + } else if (sc.Match('/', '/') || sc.Match("#REM")) { + sc.SetState(SCE_DF_COMMENTLINE); + } else if ((sc.ch == '#' && !sc.Match("#REM")) && IsFirstDataFlexWord(sc.currentPos, styler)) { + sc.SetState(SCE_DF_PREPROCESSOR); + // || (sc.ch == '|' && sc.chNext == 'C' && sc.GetRelativeCharacter(2) == 'I' && sc.GetRelativeCharacter(3) == '$') ) { + } else if ((sc.ch == '$' && ((!setWord.Contains(sc.chPrev)) || sc.chPrev == 'I' ) ) || (sc.Match("|CI$")) ) { + sc.SetState(SCE_DF_HEXNUMBER); // start with $ and previous character not in a..zA..Z0..9 excluding "I" OR start with |CI$ + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_DF_IDENTIFIER); + } else if (sc.ch == '{') { + sc.SetState(SCE_DF_METATAG); + //} else if (sc.Match("(*$")) { + // sc.SetState(SCE_DF_PREPROCESSOR2); + } else if (sc.ch == '/' && setWord.Contains(sc.chNext) && sc.atLineStart) { + sc.SetState(SCE_DF_IMAGE); + // sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.ch == '\'' || sc.ch == '\"') { + if (sc.ch == '\'' && !(curLineState & stateDoubleQuoteOpen)) { + curLineState |= stateSingleQuoteOpen; + } else if (sc.ch == '\"' && !(curLineState & stateSingleQuoteOpen)) { + curLineState |= stateDoubleQuoteOpen; + } + sc.SetState(SCE_DF_STRING); + } else if (setOperator.Contains(sc.ch)) { + sc.SetState(SCE_DF_OPERATOR); +// } else if (curLineState & stateInICode) { + // ICode start ! in a string followed by close string mark is not icode + } else if ((sc.ch == '!') && !(sc.ch == '!' && ((sc.chNext == '\"') || (sc.ch == '\'')) )) { + sc.SetState(SCE_DF_ICODE); + } + } + } + + if (sc.state == SCE_DF_IDENTIFIER && setWord.Contains(sc.chPrev)) { + ClassifyDataFlexWord(keywordlists, sc, styler); + } + + sc.Complete(); +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_DF_IMAGE; +} + +static bool IsCommentLine(Sci_Position line, Accessor &styler) { + Sci_Position pos = styler.LineStart(line); + Sci_Position eolPos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eolPos; i++) { + char ch = styler[i]; + char chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + if (ch == '/' && chNext == '/' && style == SCE_DF_COMMENTLINE) { + return true; + } else if (!IsASpaceOrTab(ch)) { + return false; + } + } + return false; +} + + + +static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) { + return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask; +} + +static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) { + lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask; + lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask; +} + +static int ClassifyDataFlexPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, + Sci_PositionU startPos, Accessor &styler) { + CharacterSet setWord(CharacterSet::setAlpha); + + char s[100]; // Size of the longest possible keyword + one additional character + null + GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s)); + size_t iLen = strnlen(s,sizeof(s)); + size_t iWordSize = 0; + + unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent); + + if (strcmp(s, "command") == 0 || + // The #if/#ifdef etcetera commands are not currently foldable as it is easy to write code that + // breaks the collaps logic, so we keep things simple and not include that for now. + strcmp(s, "header") == 0) { + nestLevel++; + SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); + lineFoldStateCurrent |= stateFoldInPreprocessor; + levelCurrent++; + iWordSize = iLen; + } else if (strcmp(s, "endcommand") == 0 || + strcmp(s, "endheader") == 0) { + nestLevel--; + SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); + if (nestLevel == 0) { + lineFoldStateCurrent &= ~stateFoldInPreprocessor; + } + levelCurrent--; + iWordSize = iLen; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } + return static_cast(iWordSize); +} + + +static void ClassifyDataFlexWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, + Sci_PositionU lastStart, Sci_PositionU currentPos, WordList *[], Accessor &styler) { + char s[100]; + + // property fold.dataflex.compilerlist + // Set to 1 for enabling the code folding feature in *.prn files + bool foldPRN = styler.GetPropertyInt("fold.dataflex.compilerlist",0) != 0; + + GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s)); + + if (strcmp(s, "case") == 0) { + lineFoldStateCurrent |= stateFoldInCaseStatement; + } else if (strcmp(s, "begin") == 0) { + levelCurrent++; + } else if (strcmp(s, "for") == 0 || + strcmp(s, "while") == 0 || + strcmp(s, "repeat") == 0 || + strcmp(s, "for_all") == 0 || + strcmp(s, "struct") == 0 || + strcmp(s, "type") == 0 || + strcmp(s, "begin_row") == 0 || + strcmp(s, "item_list") == 0 || + strcmp(s, "begin_constraints") == 0 || + strcmp(s, "begin_transaction") == 0 || + strcmp(s, "enum_list") == 0 || + strcmp(s, "class") == 0 || + strcmp(s, "object") == 0 || + strcmp(s, "cd_popup_object") == 0 || + strcmp(s, "procedure") == 0 || + strcmp(s, "procedure_section") == 0 || + strcmp(s, "function") == 0 ) { + if ((IsFirstDataFlexWord(lastStart, styler )) || foldPRN) { + levelCurrent++; + } + } else if (strcmp(s, "end") == 0) { // end is not always the first keyword, for example "case end" + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } else if (strcmp(s, "loop") == 0 || + strcmp(s, "until") == 0 || + strcmp(s, "end_class") == 0 || + strcmp(s, "end_object") == 0 || + strcmp(s, "cd_end_object") == 0 || + strcmp(s, "end_procedure") == 0 || + strcmp(s, "end_function") == 0 || + strcmp(s, "end_for_all") == 0 || + strcmp(s, "end_struct") == 0 || + strcmp(s, "end_type") == 0 || + strcmp(s, "end_row") == 0 || + strcmp(s, "end_item_list") == 0 || + strcmp(s, "end_constraints") == 0 || + strcmp(s, "end_transaction") == 0 || + strcmp(s, "end_enum_list") == 0 ) { + // lineFoldStateCurrent &= ~stateFoldInRecord; + if ((IsFirstDataFlexWord(lastStart, styler )) || foldPRN) { + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } + } + +} + + +static void ClassifyDataFlexMetaDataFoldPoint(int &levelCurrent, + Sci_PositionU lastStart, Sci_PositionU currentPos, WordList *[], Accessor &styler) { + char s[100]; + + GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s)); + + if (strcmp(s, "#beginsection") == 0) { + levelCurrent++; + } else if (strcmp(s, "#endsection") == 0) { + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } + +} + +static void FoldDataFlexDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + int iWordSize; + + Sci_Position lastStart = 0; + CharacterSet setWord(CharacterSet::setAlphaNum, "_$#@", 0x80, true); + + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext)) { + levelCurrent--; + } + } + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent+1, styler)) + levelCurrent--; + } + if (foldPreprocessor) { + if (style == SCE_DF_PREPROCESSOR) { + iWordSize = ClassifyDataFlexPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 1, styler); + //} else if (style == SCE_DF_PREPROCESSOR2 && ch == '(' && chNext == '*' + // && styler.SafeGetCharAt(i + 2) == '$') { + // ClassifyDataFlexPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler); + i = i + iWordSize; + } + } + + if (stylePrev != SCE_DF_SCOPEWORD && style == SCE_DF_SCOPEWORD) + { + // Store last word start point. + lastStart = i; + } + if (stylePrev == SCE_DF_SCOPEWORD) { + if(setWord.Contains(ch) && !setWord.Contains(chNext)) { + ClassifyDataFlexWordFoldPoint(levelCurrent, lineFoldStateCurrent, lastStart, i, keywordlists, styler); + } + } + + if (stylePrev == SCE_DF_METATAG && ch == '#') + { + // Store last word start point. + lastStart = i; + } + if (stylePrev == SCE_DF_METATAG) { + if(setWord.Contains(ch) && !setWord.Contains(chNext)) { + ClassifyDataFlexMetaDataFoldPoint(levelCurrent, lastStart, i, keywordlists, styler); + } + } + + if (!IsASpace(ch)) + visibleChars++; + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent; + styler.SetLineState(lineCurrent, newLineState); + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + } + + // If we didn't reach the EOL in previous loop, store line level and whitespace information. + // The rest will be filled in later... + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + styler.SetLevel(lineCurrent, lev); +} + +static const char * const dataflexWordListDesc[] = { + "Keywords", + "Scope open", + "Scope close", + "Operators", + 0 +}; + +extern const LexerModule lmDataflex(SCLEX_DATAFLEX, ColouriseDataFlexDoc, "dataflex", FoldDataFlexDoc, dataflexWordListDesc); diff --git a/src/lexilla/lexers/LexDiff.cxx b/src/lexilla/lexers/LexDiff.cxx new file mode 100644 index 000000000..0c6f3275b --- /dev/null +++ b/src/lexilla/lexers/LexDiff.cxx @@ -0,0 +1,155 @@ +// Scintilla source code edit control +/** @file LexDiff.cxx + ** Lexer for diff results. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +namespace { + +inline bool AtEOL(Accessor &styler, Sci_PositionU i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +void ColouriseDiffLine(const char *lineBuffer, Sci_Position endLine, Accessor &styler) { + // It is needed to remember the current state to recognize starting + // comment lines before the first "diff " or "--- ". If a real + // difference starts then each line starting with ' ' is a whitespace + // otherwise it is considered a comment (Only in..., Binary file...) + if (0 == strncmp(lineBuffer, "diff ", 5)) { + styler.ColourTo(endLine, SCE_DIFF_COMMAND); + } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff + styler.ColourTo(endLine, SCE_DIFF_COMMAND); + } else if (0 == strncmp(lineBuffer, "---", 3) && lineBuffer[3] != '-') { + // In a context diff, --- appears in both the header and the position markers + if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n') + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else if (lineBuffer[3] == ' ') + styler.ColourTo(endLine, SCE_DIFF_HEADER); + else + styler.ColourTo(endLine, SCE_DIFF_DELETED); + } else if (0 == strncmp(lineBuffer, "+++ ", 4)) { + // I don't know of any diff where "+++ " is a position marker, but for + // consistency, do the same as with "--- " and "*** ". + if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "***", 3)) { + // In a context diff, *** appears in both the header and the position markers. + // Also ******** is a chunk header, but here it's treated as part of the + // position marker since there is no separate style for a chunk header. + if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else if (lineBuffer[3] == '*') + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (lineBuffer[0] == '@') { + styler.ColourTo(endLine, SCE_DIFF_POSITION); + } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') { + styler.ColourTo(endLine, SCE_DIFF_POSITION); + } else if (0 == strncmp(lineBuffer, "++", 2)) { + styler.ColourTo(endLine, SCE_DIFF_PATCH_ADD); + } else if (0 == strncmp(lineBuffer, "+-", 2)) { + styler.ColourTo(endLine, SCE_DIFF_PATCH_DELETE); + } else if (0 == strncmp(lineBuffer, "-+", 2)) { + styler.ColourTo(endLine, SCE_DIFF_REMOVED_PATCH_ADD); + } else if (0 == strncmp(lineBuffer, "--", 2)) { + styler.ColourTo(endLine, SCE_DIFF_REMOVED_PATCH_DELETE); + } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') { + styler.ColourTo(endLine, SCE_DIFF_DELETED); + } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') { + styler.ColourTo(endLine, SCE_DIFF_ADDED); + } else if (lineBuffer[0] == '!') { + styler.ColourTo(endLine, SCE_DIFF_CHANGED); + } else if (lineBuffer[0] != ' ') { + styler.ColourTo(endLine, SCE_DIFF_COMMENT); + } else { + styler.ColourTo(endLine, SCE_DIFF_DEFAULT); + } +} + +void ColouriseDiffDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { + std::string lineBuffer; + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (Sci_PositionU i = startPos; i < startPos + length; i++) { + if (AtEOL(styler, i)) { + ColouriseDiffLine(lineBuffer.c_str(), i, styler); + lineBuffer.clear(); + } else { + lineBuffer.push_back(styler[i]); + } + } + if (!lineBuffer.empty()) { // Last line does not have ending characters + ColouriseDiffLine(lineBuffer.c_str(), startPos + length - 1, styler); + } +} + +void FoldDiffDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { + Sci_Position curLine = styler.GetLine(startPos); + Sci_Position curLineStart = styler.LineStart(curLine); + int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE; + + do { + int nextLevel = 0; + const int lineType = styler.StyleAt(curLineStart); + if (lineType == SCE_DIFF_COMMAND) + nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + else if (lineType == SCE_DIFF_HEADER) + nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG; + else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-') + nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG; + else if (prevLevel & SC_FOLDLEVELHEADERFLAG) + nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1; + else + nextLevel = prevLevel; + + if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel)) + styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG); + + styler.SetLevel(curLine, nextLevel); + prevLevel = nextLevel; + + curLineStart = styler.LineStart(++curLine); + } while (static_cast(startPos)+length > curLineStart); +} + +const char *const emptyWordListDesc[] = { + nullptr +}; + +} + +extern const LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc); diff --git a/src/lexilla/lexers/LexECL.cxx b/src/lexilla/lexers/LexECL.cxx new file mode 100644 index 000000000..8a0fb07f3 --- /dev/null +++ b/src/lexilla/lexers/LexECL.cxx @@ -0,0 +1,521 @@ +// Scintilla source code edit control +/** @file LexECL.cxx + ** Lexer for ECL. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif +#ifdef __BORLANDC__ +// Borland C++ displays warnings in vector header without this +#pragma option -w-ccc -w-rch +#endif + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#define SET_LOWER "abcdefghijklmnopqrstuvwxyz" +#define SET_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define SET_DIGITS "0123456789" + +using namespace Lexilla; + +static bool IsSpaceEquiv(int state) { + switch (state) { + case SCE_ECL_DEFAULT: + case SCE_ECL_COMMENT: + case SCE_ECL_COMMENTLINE: + case SCE_ECL_COMMENTLINEDOC: + case SCE_ECL_COMMENTDOCKEYWORD: + case SCE_ECL_COMMENTDOCKEYWORDERROR: + case SCE_ECL_COMMENTDOC: + return true; + + default: + return false; + } +} + +static void ColouriseEclDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + WordList &keywords0 = *keywordlists[0]; + WordList &keywords1 = *keywordlists[1]; + WordList &keywords2 = *keywordlists[2]; + WordList &keywords3 = *keywordlists[3]; //Value Types + WordList &keywords4 = *keywordlists[4]; + WordList &keywords5 = *keywordlists[5]; + WordList &keywords6 = *keywordlists[6]; //Javadoc Tags + WordList cplusplus; + cplusplus.Set("beginc endc"); + + bool stylingWithinPreprocessor = false; + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,"); + CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]"); + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + CharacterSet setQualified(CharacterSet::setNone, "uUxX"); + + int chPrevNonWhite = ' '; + int visibleChars = 0; + bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_ECL_DEFAULT; + bool continuationLine = false; + + if (initStyle == SCE_ECL_PREPROCESSOR) { + // Set continuationLine if last character of previous line is '\' + Sci_Position lineCurrent = styler.GetLine(startPos); + if (lineCurrent > 0) { + int chBack = styler.SafeGetCharAt(startPos-1, 0); + int chBack2 = styler.SafeGetCharAt(startPos-2, 0); + int lineEndChar = '!'; + if (chBack2 == '\r' && chBack == '\n') { + lineEndChar = styler.SafeGetCharAt(startPos-3, 0); + } else if (chBack == '\n' || chBack == '\r') { + lineEndChar = chBack2; + } + continuationLine = lineEndChar == '\\'; + } + } + + // look back to set chPrevNonWhite properly for better regex colouring + if (startPos > 0) { + Sci_Position back = startPos; + while (--back && IsSpaceEquiv(styler.StyleAt(back))) + ; + if (styler.StyleAt(back) == SCE_ECL_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineStart) { + if (sc.state == SCE_ECL_STRING) { + // Prevent SCE_ECL_STRINGEOL from leaking back to previous line which + // ends with a line continuation by locking in the state upto this position. + sc.SetState(SCE_ECL_STRING); + } + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lastWordWasUUID = false; + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continuationLine = true; + continue; + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_ECL_ADDED: + case SCE_ECL_DELETED: + case SCE_ECL_CHANGED: + case SCE_ECL_MOVED: + if (sc.atLineStart) + sc.SetState(SCE_ECL_DEFAULT); + break; + case SCE_ECL_OPERATOR: + sc.SetState(SCE_ECL_DEFAULT); + break; + case SCE_ECL_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_ECL_DEFAULT); + } + break; + case SCE_ECL_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords0.InList(s)) { + lastWordWasUUID = strcmp(s, "uuid") == 0; + sc.ChangeState(SCE_ECL_WORD0); + } else if (keywords1.InList(s)) { + sc.ChangeState(SCE_ECL_WORD1); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_ECL_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_ECL_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_ECL_WORD5); + } + else //Data types are of from KEYWORD## + { + int i = static_cast(strlen(s)) - 1; + while(i >= 0 && (isdigit(s[i]) || s[i] == '_')) + --i; + + char s2[1000]; + strncpy(s2, s, i + 1); + s2[i + 1] = 0; + if (keywords3.InList(s2)) { + sc.ChangeState(SCE_ECL_WORD3); + } + } + sc.SetState(SCE_ECL_DEFAULT); + } + break; + case SCE_ECL_PREPROCESSOR: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_ECL_DEFAULT); + } else if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_ECL_DEFAULT); + } + } else { + if (sc.Match('/', '*') || sc.Match('/', '/')) { + sc.SetState(SCE_ECL_DEFAULT); + } + } + break; + case SCE_ECL_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ECL_DEFAULT); + } + break; + case SCE_ECL_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ECL_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_ECL_COMMENTDOC; + sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); + } + } + break; + case SCE_ECL_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_ECL_DEFAULT); + } + break; + case SCE_ECL_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_ECL_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_ECL_COMMENTLINEDOC; + sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); + } + } + break; + case SCE_ECL_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_ECL_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_ECL_DEFAULT); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords6.InList(s+1)) { + sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_ECL_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ECL_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ECL_DEFAULT); + } + break; + case SCE_ECL_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ECL_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ECL_DEFAULT); + } + break; + case SCE_ECL_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_ECL_DEFAULT); + } else if (sc.ch == '/') { + sc.Forward(); + while ((sc.ch < 0x80) && islower(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_ECL_DEFAULT); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_ECL_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_ECL_DEFAULT); + } + break; + case SCE_ECL_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_ECL_DEFAULT); + } + } + break; + case SCE_ECL_UUID: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + sc.SetState(SCE_ECL_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + Sci_Position lineCurrent = styler.GetLine(sc.currentPos); + int lineState = styler.GetLineState(lineCurrent); + if (sc.state == SCE_ECL_DEFAULT) { + if (lineState) { + sc.SetState(lineState); + } + else if (sc.Match('@', '\"')) { + sc.SetState(SCE_ECL_VERBATIM); + sc.Forward(); + } else if (setQualified.Contains(sc.ch) && sc.chNext == '\'') { + sc.SetState(SCE_ECL_CHARACTER); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (lastWordWasUUID) { + sc.SetState(SCE_ECL_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_ECL_NUMBER); + } + } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + if (lastWordWasUUID) { + sc.SetState(SCE_ECL_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_ECL_IDENTIFIER); + } + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_ECL_COMMENTDOC); + } else { + sc.SetState(SCE_ECL_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_ECL_COMMENTLINEDOC); + else + sc.SetState(SCE_ECL_COMMENTLINE); + } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite)) { + sc.SetState(SCE_ECL_REGEX); // JavaScript's RegEx +// } else if (sc.ch == '\"') { +// sc.SetState(SCE_ECL_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ECL_CHARACTER); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_ECL_PREPROCESSOR); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_ECL_DEFAULT); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_ECL_OPERATOR); + } + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + continuationLine = false; + } + sc.Complete(); + +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_ECL_COMMENT || + style == SCE_ECL_COMMENTDOC || + style == SCE_ECL_COMMENTDOCKEYWORD || + style == SCE_ECL_COMMENTDOCKEYWORDERROR; +} + +static bool MatchNoCase(Accessor & styler, Sci_PositionU & pos, const char *s) { + Sci_Position i=0; + for (; *s; i++) { + char compare_char = tolower(*s); + char styler_char = tolower(styler.SafeGetCharAt(pos+i)); + if (compare_char != styler_char) + return false; + s++; + } + pos+=i-1; + return true; +} + + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldEclDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *[], Accessor &styler) { + bool foldComment = true; + bool foldPreprocessor = true; + bool foldCompact = true; + bool foldAtElse = true; + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_ECL_COMMENTLINEDOC)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_ECL_COMMENTLINEDOC) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (foldComment && (style == SCE_ECL_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + if (foldPreprocessor && (style == SCE_ECL_PREPROCESSOR)) { + if (ch == '#') { + Sci_PositionU j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (MatchNoCase(styler, j, "region") || MatchNoCase(styler, j, "if")) { + levelNext++; + } else if (MatchNoCase(styler, j, "endregion") || MatchNoCase(styler, j, "end")) { + levelNext--; + } + } + } + if (style == SCE_ECL_OPERATOR) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (style == SCE_ECL_WORD2) { + if (MatchNoCase(styler, i, "record") || MatchNoCase(styler, i, "transform") || MatchNoCase(styler, i, "type") || MatchNoCase(styler, i, "function") || + MatchNoCase(styler, i, "module") || MatchNoCase(styler, i, "service") || MatchNoCase(styler, i, "interface") || MatchNoCase(styler, i, "ifblock") || + MatchNoCase(styler, i, "macro") || MatchNoCase(styler, i, "beginc++")) { + levelNext++; + } else if (MatchNoCase(styler, i, "endmacro") || MatchNoCase(styler, i, "endc++") || MatchNoCase(styler, i, "end")) { + levelNext--; + } + } + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + if (atEOL && (i == static_cast(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + if (!IsASpace(ch)) + visibleChars++; + } +} + +static const char * const EclWordListDesc[] = { + "Keywords", + 0 +}; + +extern const LexerModule lmECL( + SCLEX_ECL, + ColouriseEclDoc, + "ecl", + FoldEclDoc, + EclWordListDesc); diff --git a/src/lexilla/lexers/LexEDIFACT.cxx b/src/lexilla/lexers/LexEDIFACT.cxx new file mode 100644 index 000000000..fcd342951 --- /dev/null +++ b/src/lexilla/lexers/LexEDIFACT.cxx @@ -0,0 +1,405 @@ +// Scintilla Lexer for EDIFACT +// @file LexEDIFACT.cxx +// Written by Iain Clarke, IMCSoft & Inobiz AB. +// EDIFACT documented here: https://www.unece.org/cefact/edifact/welcome.html +// and more readably here: https://en.wikipedia.org/wiki/EDIFACT +// This code is subject to the same license terms as the rest of the scintilla project: +// The License.txt file describes the conditions under which this software may be distributed. +// + +// Header order must match order in scripts/HeaderOrder.txt +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "LexAccessor.h" +#include "LexerModule.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +class LexerEDIFACT : public DefaultLexer +{ +public: + LexerEDIFACT(); + virtual ~LexerEDIFACT() {} // virtual destructor, as we inherit from ILexer + + static ILexer5 *Factory() { + return new LexerEDIFACT; + } + + int SCI_METHOD Version() const override + { + return lvRelease5; + } + void SCI_METHOD Release() override + { + delete this; + } + + const char * SCI_METHOD PropertyNames() override + { + return "fold\nlexer.edifact.highlight.un.all"; + } + int SCI_METHOD PropertyType(const char *) override + { + return SC_TYPE_BOOLEAN; // Only one property! + } + const char * SCI_METHOD DescribeProperty(const char *name) override + { + if (!strcmp(name, "fold")) + return "Whether to apply folding to document or not"; + if (!strcmp(name, "lexer.edifact.highlight.un.all")) + return "Whether to apply UN* highlighting to all UN segments, or just to UNH"; + return NULL; + } + + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override + { + if (!strcmp(key, "fold")) + { + m_bFold = strcmp(val, "0") ? true : false; + return 0; + } + if (!strcmp(key, "lexer.edifact.highlight.un.all")) // GetProperty + { + m_bHighlightAllUN = strcmp(val, "0") ? true : false; + return 0; + } + return -1; + } + + const char * SCI_METHOD PropertyGet(const char *key) override + { + m_lastPropertyValue = ""; + if (!strcmp(key, "fold")) + { + m_lastPropertyValue = m_bFold ? "1" : "0"; + } + if (!strcmp(key, "lexer.edifact.highlight.un.all")) // GetProperty + { + m_lastPropertyValue = m_bHighlightAllUN ? "1" : "0"; + } + return m_lastPropertyValue.c_str(); + } + + const char * SCI_METHOD DescribeWordListSets() override + { + return NULL; + } + Sci_Position SCI_METHOD WordListSet(int, const char *) override + { + return -1; + } + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void * SCI_METHOD PrivateCall(int, void *) override + { + return NULL; + } + +protected: + Sci_Position InitialiseFromUNA(IDocument *pAccess, Sci_PositionU MaxLength); + Sci_Position FindPreviousEnd(IDocument *pAccess, Sci_Position startPos) const; + Sci_Position ForwardPastWhitespace(IDocument *pAccess, Sci_Position startPos, Sci_Position MaxLength) const; + int DetectSegmentHeader(char SegmentHeader[3]) const; + + bool m_bFold; + + // property lexer.edifact.highlight.un.all + // Set to 0 to highlight only UNA segments, or 1 to highlight all UNx segments. + bool m_bHighlightAllUN; + + char m_chComponent; + char m_chData; + char m_chDecimal; + char m_chRelease; + char m_chSegment; + + std::string m_lastPropertyValue; +}; + +extern const LexerModule lmEDIFACT(SCLEX_EDIFACT, LexerEDIFACT::Factory, "edifact"); + +/////////////////////////////////////////////////////////////////////////////// + + + +/////////////////////////////////////////////////////////////////////////////// + +LexerEDIFACT::LexerEDIFACT() : DefaultLexer("edifact", SCLEX_EDIFACT) +{ + m_bFold = false; + m_bHighlightAllUN = false; + m_chComponent = ':'; + m_chData = '+'; + m_chDecimal = '.'; + m_chRelease = '?'; + m_chSegment = '\''; +} + +void LexerEDIFACT::Lex(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess) +{ + Sci_PositionU posFinish = startPos + length; + InitialiseFromUNA(pAccess, posFinish); + + // Look backwards for a ' or a document beginning + Sci_PositionU posCurrent = FindPreviousEnd(pAccess, startPos); + // And jump past the ' if this was not the beginning of the document + if (posCurrent != 0) + posCurrent++; + + // Style buffer, so we're not issuing loads of notifications + LexAccessor styler (pAccess); + pAccess->StartStyling(posCurrent); + styler.StartSegment(posCurrent); + Sci_Position posSegmentStart = -1; + + while ((posCurrent < posFinish) && (posSegmentStart == -1)) + { + posCurrent = ForwardPastWhitespace(pAccess, posCurrent, posFinish); + // Mark whitespace as default + styler.ColourTo(posCurrent - 1, SCE_EDI_DEFAULT); + if (posCurrent >= posFinish) + break; + + // Does is start with 3 charaters? ie, UNH + char SegmentHeader[4] = { 0 }; + pAccess->GetCharRange(SegmentHeader, posCurrent, 3); + + int SegmentStyle = DetectSegmentHeader(SegmentHeader); + if (SegmentStyle == SCE_EDI_BADSEGMENT) + break; + if (SegmentStyle == SCE_EDI_UNA) + { + posCurrent += 9; + styler.ColourTo(posCurrent - 1, SCE_EDI_UNA); // UNA + continue; + } + posSegmentStart = posCurrent; + posCurrent += 3; + + styler.ColourTo(posCurrent - 1, SegmentStyle); // UNH etc + + // Colour in the rest of the segment + for (char c; posCurrent < posFinish; posCurrent++) + { + pAccess->GetCharRange(&c, posCurrent, 1); + + if (c == m_chRelease) // ? escape character, check first, in case of ?' + posCurrent++; + else if (c == m_chSegment) // ' + { + // Make sure the whole segment is on one line. styler won't let us go back in time, so we'll settle for marking the ' as bad. + Sci_Position lineSegmentStart = pAccess->LineFromPosition(posSegmentStart); + Sci_Position lineSegmentEnd = pAccess->LineFromPosition(posCurrent); + if (lineSegmentStart == lineSegmentEnd) + styler.ColourTo(posCurrent, SCE_EDI_SEGMENTEND); + else + styler.ColourTo(posCurrent, SCE_EDI_BADSEGMENT); + posSegmentStart = -1; + posCurrent++; + break; + } + else if (c == m_chComponent) // : + styler.ColourTo(posCurrent, SCE_EDI_SEP_COMPOSITE); + else if (c == m_chData) // + + styler.ColourTo(posCurrent, SCE_EDI_SEP_ELEMENT); + else + styler.ColourTo(posCurrent, SCE_EDI_DEFAULT); + } + } + styler.Flush(); + + if (posSegmentStart == -1) + return; + + pAccess->StartStyling(posSegmentStart); + pAccess->SetStyleFor(posFinish - posSegmentStart, SCE_EDI_BADSEGMENT); +} + +void LexerEDIFACT::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess) +{ + if (!m_bFold) + return; + + Sci_PositionU endPos = startPos + length; + startPos = FindPreviousEnd(pAccess, startPos); + char c; + char SegmentHeader[4] = { 0 }; + + bool AwaitingSegment = true; + Sci_PositionU currLine = pAccess->LineFromPosition(startPos); + int levelCurrentStyle = SC_FOLDLEVELBASE; + if (currLine > 0) + levelCurrentStyle = pAccess->GetLevel(currLine - 1); // bottom 12 bits are level + int indentCurrent = levelCurrentStyle & SC_FOLDLEVELNUMBERMASK; + int indentNext = indentCurrent; + + while (startPos < endPos) + { + pAccess->GetCharRange(&c, startPos, 1); + switch (c) + { + case '\t': + case '\r': + case ' ': + startPos++; + continue; + case '\n': + currLine = pAccess->LineFromPosition(startPos); + pAccess->SetLevel(currLine, levelCurrentStyle | indentCurrent); + startPos++; + levelCurrentStyle = SC_FOLDLEVELBASE; + indentCurrent = indentNext; + continue; + } + if (c == m_chRelease) + { + startPos += 2; + continue; + } + if (c == m_chSegment) + { + AwaitingSegment = true; + startPos++; + continue; + } + + if (!AwaitingSegment) + { + startPos++; + continue; + } + + // Segment! + pAccess->GetCharRange(SegmentHeader, startPos, 3); + if (SegmentHeader[0] != 'U' || SegmentHeader[1] != 'N') + { + startPos++; + continue; + } + + AwaitingSegment = false; + switch (SegmentHeader[2]) + { + case 'H': + case 'G': + indentNext++; + levelCurrentStyle = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + break; + + case 'T': + case 'E': + if (indentNext > 0) + indentNext--; + break; + } + + startPos += 3; + } +} + +Sci_Position LexerEDIFACT::InitialiseFromUNA(IDocument *pAccess, Sci_PositionU MaxLength) +{ + MaxLength -= 9; // drop 9 chars, to give us room for UNA:+.? ' + + Sci_PositionU startPos = 0; + startPos += ForwardPastWhitespace(pAccess, 0, MaxLength); + if (startPos < MaxLength) + { + char bufUNA[9]; + pAccess->GetCharRange(bufUNA, startPos, 9); + + // Check it's UNA segment + if (!memcmp(bufUNA, "UNA", 3)) + { + m_chComponent = bufUNA[3]; + m_chData = bufUNA[4]; + m_chDecimal = bufUNA[5]; + m_chRelease = bufUNA[6]; + // bufUNA [7] should be space - reserved. + m_chSegment = bufUNA[8]; + + return 0; // success! + } + } + + // We failed to find a UNA, so drop to defaults + m_chComponent = ':'; + m_chData = '+'; + m_chDecimal = '.'; + m_chRelease = '?'; + m_chSegment = '\''; + + return -1; +} + +Sci_Position LexerEDIFACT::ForwardPastWhitespace(IDocument *pAccess, Sci_Position startPos, Sci_Position MaxLength) const +{ + char c; + + while (startPos < MaxLength) + { + pAccess->GetCharRange(&c, startPos, 1); + switch (c) + { + case '\t': + case '\r': + case '\n': + case ' ': + break; + default: + return startPos; + } + + startPos++; + } + + return MaxLength; +} + +int LexerEDIFACT::DetectSegmentHeader(char SegmentHeader[3]) const +{ + if ( + SegmentHeader[0] < 'A' || SegmentHeader[0] > 'Z' || + SegmentHeader[1] < 'A' || SegmentHeader[1] > 'Z' || + SegmentHeader[2] < 'A' || SegmentHeader[2] > 'Z') + return SCE_EDI_BADSEGMENT; + + if (!memcmp(SegmentHeader, "UNA", 3)) + return SCE_EDI_UNA; + + if (m_bHighlightAllUN && !memcmp(SegmentHeader, "UN", 2)) + return SCE_EDI_UNH; + else if (!memcmp(SegmentHeader, "UNH", 3)) + return SCE_EDI_UNH; + else if (!memcmp(SegmentHeader, "UNG", 3)) + return SCE_EDI_UNH; + + return SCE_EDI_SEGMENTSTART; +} + +// Look backwards for a ' or a document beginning +Sci_Position LexerEDIFACT::FindPreviousEnd(IDocument *pAccess, Sci_Position startPos) const +{ + for (char c; startPos > 0; startPos--) + { + pAccess->GetCharRange(&c, startPos, 1); + if (c == m_chSegment) + return startPos; + } + // We didn't find a ', so just go with the beginning + return 0; +} + + diff --git a/src/lexilla/lexers/LexEScript.cxx b/src/lexilla/lexers/LexEScript.cxx new file mode 100644 index 000000000..079898de3 --- /dev/null +++ b/src/lexilla/lexers/LexEScript.cxx @@ -0,0 +1,277 @@ +// Scintilla source code edit control +/** @file LexEScript.cxx + ** Lexer for ESCRIPT + **/ +// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com) + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + + + +static void ColouriseESCRIPTDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + + // Do not leak onto next line + /*if (initStyle == SCE_ESCRIPT_STRINGEOL) + initStyle = SCE_ESCRIPT_DEFAULT;*/ + + StyleContext sc(startPos, length, initStyle, styler); + + bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0; + + for (; sc.More(); sc.Forward()) { + + /*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) { + // Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line + sc.SetState(SCE_ESCRIPT_STRING); + }*/ + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } else if (sc.state == SCE_ESCRIPT_NUMBER) { + if (!IsADigit(sc.ch) || sc.ch != '.') { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + +// sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD3); + // sc.state = SCE_ESCRIPT_IDENTIFIER; + } + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENT) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENTDOC) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENTLINE) { + if (sc.atLineEnd) { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ESCRIPT_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_ESCRIPT_NUMBER); + } else if (IsAWordStart(sc.ch) || (sc.ch == '#')) { + sc.SetState(SCE_ESCRIPT_IDENTIFIER); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_ESCRIPT_COMMENT); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_ESCRIPT_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ESCRIPT_STRING); + //} else if (isoperator(static_cast(sc.ch))) { + } else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') { + sc.SetState(SCE_ESCRIPT_OPERATOR); + } else if (sc.ch == '{' || sc.ch == '}') { + sc.SetState(SCE_ESCRIPT_BRACE); + } + } + + } + sc.Complete(); +} + + +static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) { + int lev = 0; + if (strcmp(prevWord, "end") == 0) return lev; + if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) + return -1; + + if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0 + || strcmp(s, "program") == 0 || strcmp(s, "function") == 0 + || strcmp(s, "while") == 0 || strcmp(s, "case") == 0 + || strcmp(s, "if") == 0 ) { + lev = 1; + } else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0 + || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0 + || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0 + || strcmp(s, "endif") == 0 ) { + lev = -1; + } + + return lev; +} + + +static bool IsStreamCommentStyle(int style) { + return style == SCE_ESCRIPT_COMMENT || + style == SCE_ESCRIPT_COMMENTDOC || + style == SCE_ESCRIPT_COMMENTLINE; +} + +static void FoldESCRIPTDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], Accessor &styler) { + //~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + // Do not know how to fold the comment at the moment. + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldComment = true; + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + Sci_Position lastStart = 0; + char prevWord[32] = ""; + + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + + if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3) + { + // Store last word start point. + lastStart = i; + } + + if (style == SCE_ESCRIPT_WORD3) { + if(iswordchar(ch) && !iswordchar(chNext)) { + char s[32]; + Sci_PositionU j; + for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) { + s[j] = static_cast(tolower(styler[lastStart + j])); + } + s[j] = '\0'; + levelCurrent += classifyFoldPointESCRIPT(s, prevWord); + strcpy(prevWord, s); + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + strcpy(prevWord, ""); + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + + + +static const char * const ESCRIPTWordLists[] = { + "Primary keywords and identifiers", + "Intrinsic functions", + "Extended and user defined functions", + 0, +}; + +extern const LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists); diff --git a/src/lexilla/lexers/LexEiffel.cxx b/src/lexilla/lexers/LexEiffel.cxx new file mode 100644 index 000000000..7a8014c97 --- /dev/null +++ b/src/lexilla/lexers/LexEiffel.cxx @@ -0,0 +1,242 @@ +// Scintilla source code edit control +/** @file LexEiffel.cxx + ** Lexer for Eiffel. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool isEiffelOperator(unsigned int ch) { + // '.' left out as it is used to make up numbers + return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || + ch == '{' || ch == '}' || ch == '~' || + ch == '[' || ch == ']' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || + ch == '.' || ch == '^' || ch == '%' || ch == ':' || + ch == '!' || ch == '@' || ch == '?'; +} + +static inline bool IsAWordChar(unsigned int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(unsigned int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColouriseEiffelDoc(Sci_PositionU startPos, + Sci_Position length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_EIFFEL_STRINGEOL) { + if (sc.ch != '\r' && sc.ch != '\n') { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_OPERATOR) { + sc.SetState(SCE_EIFFEL_DEFAULT); + } else if (sc.state == SCE_EIFFEL_WORD) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!keywords.InList(s)) { + sc.ChangeState(SCE_EIFFEL_IDENTIFIER); + } + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_COMMENTLINE) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_STRING) { + if (sc.ch == '%') { + sc.Forward(); + } else if (sc.ch == '\"') { + sc.Forward(); + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_CHARACTER) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_EIFFEL_STRINGEOL); + } else if (sc.ch == '%') { + sc.Forward(); + } else if (sc.ch == '\'') { + sc.Forward(); + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } + + if (sc.state == SCE_EIFFEL_DEFAULT) { + if (sc.ch == '-' && sc.chNext == '-') { + sc.SetState(SCE_EIFFEL_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_EIFFEL_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_EIFFEL_CHARACTER); + } else if (IsADigit(sc.ch) || (sc.ch == '.')) { + sc.SetState(SCE_EIFFEL_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_EIFFEL_WORD); + } else if (isEiffelOperator(sc.ch)) { + sc.SetState(SCE_EIFFEL_OPERATOR); + } + } + } + sc.Complete(); +} + +static bool IsEiffelComment(Accessor &styler, Sci_Position pos, Sci_Position len) { + return len>1 && styler[pos]=='-' && styler[pos+1]=='-'; +} + +static void FoldEiffelDocIndent(Sci_PositionU startPos, Sci_Position length, int, + WordList *[], Accessor &styler) { + Sci_Position lengthDoc = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + Sci_Position lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment); + char chNext = styler[startPos]; + for (Sci_Position i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + // Only non whitespace lines can be headers + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + // Line after is blank so check the next - maybe should continue further? + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static void FoldEiffelDocKeyWords(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[], + Accessor &styler) { + Sci_PositionU lengthDoc = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int stylePrev = 0; + int styleNext = styler.StyleAt(startPos); + // lastDeferred should be determined by looking back to last keyword in case + // the "deferred" is on a line before "class" + bool lastDeferred = false; + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) { + char s[20]; + Sci_PositionU j = 0; + while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { + s[j] = styler[i + j]; + j++; + } + s[j] = '\0'; + + if ( + (strcmp(s, "check") == 0) || + (strcmp(s, "debug") == 0) || + (strcmp(s, "deferred") == 0) || + (strcmp(s, "do") == 0) || + (strcmp(s, "from") == 0) || + (strcmp(s, "if") == 0) || + (strcmp(s, "inspect") == 0) || + (strcmp(s, "once") == 0) + ) + levelCurrent++; + if (!lastDeferred && (strcmp(s, "class") == 0)) + levelCurrent++; + if (strcmp(s, "end") == 0) + levelCurrent--; + lastDeferred = strcmp(s, "deferred") == 0; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + stylePrev = style; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const eiffelWordListDesc[] = { + "Keywords", + 0 +}; + +extern const LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc); +extern const LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc); diff --git a/src/lexilla/lexers/LexErlang.cxx b/src/lexilla/lexers/LexErlang.cxx new file mode 100644 index 000000000..0aace04cf --- /dev/null +++ b/src/lexilla/lexers/LexErlang.cxx @@ -0,0 +1,631 @@ +// Scintilla source code edit control +// Encoding: UTF-8 +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +/** @file LexErlang.cxx + ** Lexer for Erlang. + ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com) + ** Originally wrote by Peter-Henry Mander, + ** based on Matlab lexer by José Fonseca. + **/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static int is_radix(int radix, int ch) { + int digit; + + if (36 < radix || 2 > radix) + return 0; + + if (isdigit(ch)) { + digit = ch - '0'; + } else if (isalnum(ch)) { + digit = toupper(ch) - 'A' + 10; + } else { + return 0; + } + + return (digit < radix); +} + +typedef enum { + STATE_NULL, + COMMENT, + COMMENT_FUNCTION, + COMMENT_MODULE, + COMMENT_DOC, + COMMENT_DOC_MACRO, + ATOM_UNQUOTED, + ATOM_QUOTED, + NODE_NAME_UNQUOTED, + NODE_NAME_QUOTED, + MACRO_START, + MACRO_UNQUOTED, + MACRO_QUOTED, + RECORD_START, + RECORD_UNQUOTED, + RECORD_QUOTED, + NUMERAL_START, + NUMERAL_BASE_VALUE, + NUMERAL_FLOAT, + NUMERAL_EXPONENT, + PREPROCESSOR +} atom_parse_state_t; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (ch != ' ') && (isalnum(ch) || ch == '_'); +} + +static void ColouriseErlangDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + StyleContext sc(startPos, length, initStyle, styler); + WordList &reservedWords = *keywordlists[0]; + WordList &erlangBIFs = *keywordlists[1]; + WordList &erlangPreproc = *keywordlists[2]; + WordList &erlangModulesAtt = *keywordlists[3]; + WordList &erlangDoc = *keywordlists[4]; + WordList &erlangDocMacro = *keywordlists[5]; + int radix_digits = 0; + int exponent_digits = 0; + atom_parse_state_t parse_state = STATE_NULL; + atom_parse_state_t old_parse_state = STATE_NULL; + bool to_late_to_comment = false; + char cur[100]; + int old_style = SCE_ERLANG_DEFAULT; + + styler.StartAt(startPos); + + for (; sc.More(); sc.Forward()) { + int style = SCE_ERLANG_DEFAULT; + if (STATE_NULL != parse_state) { + + switch (parse_state) { + + case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break; + + /* COMMENTS ------------------------------------------------------*/ + case COMMENT : { + if (sc.ch != '%') { + to_late_to_comment = true; + } else if (!to_late_to_comment && sc.ch == '%') { + // Switch to comment level 2 (Function) + sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION); + old_style = SCE_ERLANG_COMMENT_FUNCTION; + parse_state = COMMENT_FUNCTION; + sc.Forward(); + } + } + // V--- Falling through! + // Falls through. + case COMMENT_FUNCTION : { + if (sc.ch != '%') { + to_late_to_comment = true; + } else if (!to_late_to_comment && sc.ch == '%') { + // Switch to comment level 3 (Module) + sc.ChangeState(SCE_ERLANG_COMMENT_MODULE); + old_style = SCE_ERLANG_COMMENT_MODULE; + parse_state = COMMENT_MODULE; + sc.Forward(); + } + } + // V--- Falling through! + // Falls through. + case COMMENT_MODULE : { + if (parse_state != COMMENT) { + // Search for comment documentation + if (sc.chNext == '@') { + old_parse_state = parse_state; + parse_state = ('{' == sc.ch) + ? COMMENT_DOC_MACRO + : COMMENT_DOC; + sc.ForwardSetState(sc.state); + } + } + + // All comments types fall here. + if (sc.MatchLineEnd()) { + to_late_to_comment = false; + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case COMMENT_DOC : + // V--- Falling through! + case COMMENT_DOC_MACRO : { + + if (!isalnum(sc.ch)) { + // Try to match documentation comment + sc.GetCurrent(cur, sizeof(cur)); + + if (parse_state == COMMENT_DOC_MACRO + && erlangDocMacro.InList(cur)) { + sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO); + while (sc.ch != '}' && !sc.atLineEnd) + sc.Forward(); + } else if (erlangDoc.InList(cur)) { + sc.ChangeState(SCE_ERLANG_COMMENT_DOC); + } else { + sc.ChangeState(old_style); + } + + // Switch back to old state + sc.SetState(old_style); + parse_state = old_parse_state; + } + + if (sc.MatchLineEnd()) { + to_late_to_comment = false; + sc.ChangeState(old_style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Atoms ---------------------------------------------------------*/ + case ATOM_UNQUOTED : { + if ('@' == sc.ch){ + parse_state = NODE_NAME_UNQUOTED; + } else if (sc.ch == ':') { + // Searching for module name + if (sc.chNext == ' ') { + // error + sc.ChangeState(SCE_ERLANG_UNKNOWN); + parse_state = STATE_NULL; + } else { + sc.Forward(); + if (isalnum(sc.ch) || (sc.ch == '\'')) { + sc.GetCurrent(cur, sizeof(cur)); + sc.ChangeState(SCE_ERLANG_MODULES); + sc.SetState(SCE_ERLANG_MODULES); + } + if (sc.ch == '\'') { + parse_state = ATOM_QUOTED; + } + + } + } else if (!IsAWordChar(sc.ch)) { + + sc.GetCurrent(cur, sizeof(cur)); + if (reservedWords.InList(cur)) { + style = SCE_ERLANG_KEYWORD; + } else if (erlangBIFs.InList(cur) + && strcmp(cur,"erlang:")){ + style = SCE_ERLANG_BIFS; + } else if (sc.ch == '(' || '/' == sc.ch){ + style = SCE_ERLANG_FUNCTION_NAME; + } else { + style = SCE_ERLANG_ATOM; + } + + sc.ChangeState(style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + + } break; + + case ATOM_QUOTED : { + if ( '@' == sc.ch ){ + parse_state = NODE_NAME_QUOTED; + } else if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_ATOM_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Node names ----------------------------------------------------*/ + case NODE_NAME_UNQUOTED : { + if ('@' == sc.ch) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_NODE_NAME); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case NODE_NAME_QUOTED : { + if ('@' == sc.ch) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Records -------------------------------------------------------*/ + case RECORD_START : { + if ('\'' == sc.ch) { + parse_state = RECORD_QUOTED; + } else if (isalpha(sc.ch) && islower(sc.ch)) { + parse_state = RECORD_UNQUOTED; + } else { // error + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case RECORD_UNQUOTED : { + if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_RECORD); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case RECORD_QUOTED : { + if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_RECORD_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Macros --------------------------------------------------------*/ + case MACRO_START : { + if ('\'' == sc.ch) { + parse_state = MACRO_QUOTED; + } else if (isalpha(sc.ch)) { + parse_state = MACRO_UNQUOTED; + } else { // error + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case MACRO_UNQUOTED : { + if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_MACRO); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case MACRO_QUOTED : { + if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_MACRO_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Numerics ------------------------------------------------------*/ + /* Simple integer */ + case NUMERAL_START : { + if (isdigit(sc.ch)) { + radix_digits *= 10; + radix_digits += sc.ch - '0'; // Assuming ASCII here! + } else if ('#' == sc.ch) { + if (2 > radix_digits || 36 < radix_digits) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else { + parse_state = NUMERAL_BASE_VALUE; + } + } else if ('.' == sc.ch && isdigit(sc.chNext)) { + radix_digits = 0; + parse_state = NUMERAL_FLOAT; + } else if ('e' == sc.ch || 'E' == sc.ch) { + exponent_digits = 0; + parse_state = NUMERAL_EXPONENT; + } else { + radix_digits = 0; + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Integer in other base than 10 (x#yyy) */ + case NUMERAL_BASE_VALUE : { + if (!is_radix(radix_digits,sc.ch)) { + radix_digits = 0; + + if (!isalnum(sc.ch)) + sc.ChangeState(SCE_ERLANG_NUMBER); + + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Float (x.yyy) */ + case NUMERAL_FLOAT : { + if ('e' == sc.ch || 'E' == sc.ch) { + exponent_digits = 0; + parse_state = NUMERAL_EXPONENT; + } else if (!isdigit(sc.ch)) { + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Exponent, either integer or float (xEyy, x.yyEzzz) */ + case NUMERAL_EXPONENT : { + if (('-' == sc.ch || '+' == sc.ch) + && (isdigit(sc.chNext))) { + sc.Forward(); + } else if (!isdigit(sc.ch)) { + if (0 < exponent_digits) + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else { + ++exponent_digits; + } + } break; + + /* -------------------------------------------------------------- */ + /* Preprocessor --------------------------------------------------*/ + case PREPROCESSOR : { + if (!IsAWordChar(sc.ch)) { + + sc.GetCurrent(cur, sizeof(cur)); + if (erlangPreproc.InList(cur)) { + style = SCE_ERLANG_PREPROC; + } else if (erlangModulesAtt.InList(cur)) { + style = SCE_ERLANG_MODULES_ATT; + } + + sc.ChangeState(style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + } + + } /* End of : STATE_NULL != parse_state */ + else + { + switch (sc.state) { + case SCE_ERLANG_VARIABLE : { + if (!IsAWordChar(sc.ch)) + sc.SetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_STRING : { + if (sc.ch == '\"' && sc.chPrev != '\\') + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_COMMENT : { + if (sc.atLineEnd) + sc.SetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_CHARACTER : { + if (sc.chPrev == '\\') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else if (sc.ch != '\\') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } + } break; + case SCE_ERLANG_OPERATOR : { + if (sc.chPrev == '.') { + if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' + || sc.ch == '^') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else { + sc.SetState(SCE_ERLANG_DEFAULT); + } + } else { + sc.SetState(SCE_ERLANG_DEFAULT); + } + } break; + } + } + + if (sc.state == SCE_ERLANG_DEFAULT) { + bool no_new_state = false; + + switch (sc.ch) { + case '\"' : sc.SetState(SCE_ERLANG_STRING); break; + case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break; + case '%' : { + parse_state = COMMENT; + sc.SetState(SCE_ERLANG_COMMENT); + } break; + case '#' : { + parse_state = RECORD_START; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '?' : { + parse_state = MACRO_START; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '\'' : { + parse_state = ATOM_QUOTED; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '+' : + case '-' : { + if (IsADigit(sc.chNext)) { + parse_state = NUMERAL_START; + radix_digits = 0; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (sc.ch != '+') { + parse_state = PREPROCESSOR; + sc.SetState(SCE_ERLANG_UNKNOWN); + } + } break; + default : no_new_state = true; + } + + if (no_new_state) { + if (isdigit(sc.ch)) { + parse_state = NUMERAL_START; + radix_digits = sc.ch - '0'; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (isupper(sc.ch) || '_' == sc.ch) { + sc.SetState(SCE_ERLANG_VARIABLE); + } else if (isalpha(sc.ch)) { + parse_state = ATOM_UNQUOTED; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (isoperator(static_cast(sc.ch)) + || sc.ch == '\\') { + sc.SetState(SCE_ERLANG_OPERATOR); + } + } + } + + } + sc.Complete(); +} + +static int ClassifyErlangFoldPoint( + Accessor &styler, + int styleNext, + Sci_Position keyword_start +) { + int lev = 0; + if (styler.Match(keyword_start,"case") + || ( + styler.Match(keyword_start,"fun") + && (SCE_ERLANG_FUNCTION_NAME != styleNext) + ) + || styler.Match(keyword_start,"if") + || styler.Match(keyword_start,"query") + || styler.Match(keyword_start,"receive") + ) { + ++lev; + } else if (styler.Match(keyword_start,"end")) { + --lev; + } + + return lev; +} + +static void FoldErlangDoc( + Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList** /*keywordlists*/, Accessor &styler +) { + Sci_PositionU endPos = startPos + length; + Sci_Position currentLine = styler.GetLine(startPos); + int lev; + int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK; + int currentLevel = previousLevel; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + int stylePrev; + Sci_Position keyword_start = 0; + char ch; + char chNext = styler.SafeGetCharAt(startPos); + bool atEOL; + + for (Sci_PositionU i = startPos; i < endPos; i++) { + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + // Get styles + stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n'); + + if (stylePrev != SCE_ERLANG_KEYWORD + && style == SCE_ERLANG_KEYWORD) { + keyword_start = i; + } + + // Fold on keywords + if (stylePrev == SCE_ERLANG_KEYWORD + && style != SCE_ERLANG_KEYWORD + && style != SCE_ERLANG_ATOM + ) { + currentLevel += ClassifyErlangFoldPoint(styler, + styleNext, + keyword_start); + } + + // Fold on comments + if (style == SCE_ERLANG_COMMENT + || style == SCE_ERLANG_COMMENT_MODULE + || style == SCE_ERLANG_COMMENT_FUNCTION) { + + if (ch == '%' && chNext == '{') { + currentLevel++; + } else if (ch == '%' && chNext == '}') { + currentLevel--; + } + } + + // Fold on braces + if (style == SCE_ERLANG_OPERATOR) { + if (ch == '{' || ch == '(' || ch == '[') { + currentLevel++; + } else if (ch == '}' || ch == ')' || ch == ']') { + currentLevel--; + } + } + + + if (atEOL) { + lev = previousLevel; + + if (currentLevel > previousLevel) + lev |= SC_FOLDLEVELHEADERFLAG; + + if (lev != styler.LevelAt(currentLine)) + styler.SetLevel(currentLine, lev); + + currentLine++; + previousLevel = currentLevel; + } + + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + styler.SetLevel(currentLine, + previousLevel + | (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK)); +} + +static const char * const erlangWordListDesc[] = { + "Erlang Reserved words", + "Erlang BIFs", + "Erlang Preprocessor", + "Erlang Module Attributes", + "Erlang Documentation", + "Erlang Documentation Macro", + 0 +}; + +extern const LexerModule lmErlang( + SCLEX_ERLANG, + ColouriseErlangDoc, + "erlang", + FoldErlangDoc, + erlangWordListDesc); diff --git a/src/lexilla/lexers/LexErrorList.cxx b/src/lexilla/lexers/LexErrorList.cxx new file mode 100644 index 000000000..dcdf0ce32 --- /dev/null +++ b/src/lexilla/lexers/LexErrorList.cxx @@ -0,0 +1,431 @@ +// Scintilla source code edit control +/** @file LexErrorList.cxx + ** Lexer for error lists. Used for the output pane in SciTE. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "InList.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +namespace { + +bool strstart(const char *haystack, const char *needle) noexcept { + return strncmp(haystack, needle, strlen(needle)) == 0; +} + +constexpr bool Is0To9(char ch) noexcept { + return (ch >= '0') && (ch <= '9'); +} + +constexpr bool Is1To9(char ch) noexcept { + return (ch >= '1') && (ch <= '9'); +} + +bool AtEOL(Accessor &styler, Sci_Position i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +bool IsGccExcerpt(const char *s) noexcept { + while (*s) { + if (s[0] == ' ' && s[1] == '|' && (s[2] == ' ' || s[2] == '+')) { + return true; + } + if (!(s[0] == ' ' || s[0] == '+' || Is0To9(s[0]))) { + return false; + } + s++; + } + return true; +} + +const std::string_view bashDiagnosticMark = ": line "; +bool IsBashDiagnostic(std::string_view sv) { + const size_t mark = sv.find(bashDiagnosticMark); + if (mark == std::string_view::npos) { + return false; + } + std::string_view rest = sv.substr(mark + bashDiagnosticMark.length()); + if (rest.empty() || !Is0To9(rest.front())) { + return false; + } + while (!rest.empty() && Is0To9(rest.front())) { + rest.remove_prefix(1); + } + return !rest.empty() && (rest.front() == ':'); +} + + +int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLine, Sci_Position &startValue) { + if (lineBuffer[0] == '>') { + // Command or return status + return SCE_ERR_CMD; + } else if (lineBuffer[0] == '<') { + // Diff removal. + return SCE_ERR_DIFF_DELETION; + } else if (lineBuffer[0] == '!') { + return SCE_ERR_DIFF_CHANGED; + } else if (lineBuffer[0] == '+') { + if (strstart(lineBuffer, "+++ ")) { + return SCE_ERR_DIFF_MESSAGE; + } else { + return SCE_ERR_DIFF_ADDITION; + } + } else if (lineBuffer[0] == '-') { + if (strstart(lineBuffer, "--- ")) { + return SCE_ERR_DIFF_MESSAGE; + } else { + return SCE_ERR_DIFF_DELETION; + } + } else if (strstart(lineBuffer, "cf90-")) { + // Absoft Pro Fortran 90/95 v8.2 error and/or warning message + return SCE_ERR_ABSF; + } else if (strstart(lineBuffer, "fortcom:")) { + // Intel Fortran Compiler v8.0 error/warning message + return SCE_ERR_IFORT; + } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) { + return SCE_ERR_PYTHON; + } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) { + return SCE_ERR_PHP; + } else if ((strstart(lineBuffer, "Error ") || + strstart(lineBuffer, "Warning ")) && + strstr(lineBuffer, " at (") && + strstr(lineBuffer, ") : ") && + (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) { + // Intel Fortran Compiler error/warning message + return SCE_ERR_IFC; + } else if (strstart(lineBuffer, "Error ")) { + // Borland error message + return SCE_ERR_BORLAND; + } else if (strstart(lineBuffer, "Warning ")) { + // Borland warning message + return SCE_ERR_BORLAND; + } else if (strstr(lineBuffer, "at line ") && + (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) && + strstr(lineBuffer, "file ") && + (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) { + // Lua 4 error message + return SCE_ERR_LUA; + } else if (strstr(lineBuffer, " at ") && + (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) && + strstr(lineBuffer, " line ") && + (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) && + (strstr(lineBuffer, " at ") + 4 < (strstr(lineBuffer, " line ")))) { + // perl error message: + // at line + return SCE_ERR_PERL; + } else if ((lengthLine >= 6) && + (memcmp(lineBuffer, " at ", 6) == 0) && + strstr(lineBuffer, ":line ")) { + // A .NET traceback + return SCE_ERR_NET; + } else if (strstart(lineBuffer, "Line ") && + strstr(lineBuffer, ", file ")) { + // Essential Lahey Fortran error message + return SCE_ERR_ELF; + } else if (strstart(lineBuffer, "line ") && + strstr(lineBuffer, " column ")) { + // HTML tidy style: line 42 column 1 + return SCE_ERR_TIDY; + } else if (strstart(lineBuffer, "\tat ") && + strchr(lineBuffer, '(') && + strstr(lineBuffer, ".java:")) { + // Java stack back trace + return SCE_ERR_JAVA_STACK; + } else if (strstart(lineBuffer, "In file included from ") || + strstart(lineBuffer, " from ")) { + // GCC showing include path to following error + return SCE_ERR_GCC_INCLUDED_FROM; + } else if (strstart(lineBuffer, "NMAKE : fatal error")) { + // Microsoft nmake fatal error: + // NMAKE : fatal error : : return code + return SCE_ERR_MS; + } else if (strstr(lineBuffer, "warning LNK") || + strstr(lineBuffer, "error LNK")) { + // Microsoft linker warning: + // { : } (warning|error) LNK9999 + return SCE_ERR_MS; + } else if (IsBashDiagnostic(lineBuffer)) { + // Bash diagnostic + // : line : + return SCE_ERR_BASH; + } else if (IsGccExcerpt(lineBuffer)) { + // GCC code excerpt and pointer to issue + // 73 | GTimeVal last_popdown; + // | ^~~~~~~~~~~~ + return SCE_ERR_GCC_EXCERPT; + } else { + // Look for one of the following formats: + // GCC: :: + // Microsoft: () : + // Common: (): warning|error|note|remark|catastrophic|fatal + // Common: () warning|error|note|remark|catastrophic|fatal + // Microsoft: (,) + // CTags: \t\t + // Lua 5 traceback: \t:: + // Lua 5.1: : :: + const bool initialTab = (lineBuffer[0] == '\t'); + bool initialColonPart = false; + bool canBeCtags = !initialTab; // For ctags must have an identifier with no spaces then a tab + enum { stInitial, + stGccStart, stGccDigit, stGccColumn, stGcc, + stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, + stCtagsStart, stCtagsFile, stCtagsStartString, stCtagsStringDollar, stCtags, + stUnrecognized + } state = stInitial; + for (Sci_PositionU i = 0; i < lengthLine; i++) { + const char ch = lineBuffer[i]; + char chNext = ' '; + if ((i + 1) < lengthLine) + chNext = lineBuffer[i + 1]; + if (state == stInitial) { + if (ch == ':') { + // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix) + if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) { + // This check is not completely accurate as may be on + // GTK+ with a file name that includes ':'. + state = stGccStart; + } else if (chNext == ' ') { // indicates a Lua 5.1 error message + initialColonPart = true; + } + } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) { + // May be Microsoft + // Check against '0' often removes phone numbers + state = stMsStart; + } else if ((ch == '\t') && canBeCtags) { + // May be CTags + state = stCtagsStart; + } else if (ch == ' ') { + canBeCtags = false; + } + } else if (state == stGccStart) { // : + state = ((ch == '-') || Is0To9(ch)) ? stGccDigit : stUnrecognized; + } else if (state == stGccDigit) { // : + if (ch == ':') { + state = stGccColumn; // :9.*: is GCC + startValue = i + 1; + } else if (!Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stGccColumn) { // :: + if (!Is0To9(ch)) { + state = stGcc; + if (ch == ':') + startValue = i + 1; + break; + } + } else if (state == stMsStart) { // ( + state = Is0To9(ch) ? stMsDigit : stUnrecognized; + } else if (state == stMsDigit) { // ( + if (ch == ',') { + state = stMsDigitComma; + } else if (ch == ')') { + state = stMsBracket; + } else if ((ch != ' ') && !Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stMsBracket) { // () + if ((ch == ' ') && (chNext == ':')) { + state = stMsVc; + } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) { + // Possibly Delphi.. don't test against chNext as it's one of the strings below. + char word[512]; + unsigned numstep = 0; + if (ch == ' ') + numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i. + else + numstep = 2; // otherwise add 2. + Sci_PositionU chPos = 0; + for (Sci_PositionU j = i + numstep; j < lengthLine && IsUpperOrLowerCase(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) + word[chPos++] = lineBuffer[j]; + word[chPos] = 0; + if (InListCaseInsensitive(word, {"error", "warning", "fatal", "catastrophic", "note", "remark"})) { + state = stMsVc; + } else { + state = stUnrecognized; + } + } else { + state = stUnrecognized; + } + } else if (state == stMsDigitComma) { // (, + if (ch == ')') { + state = stMsDotNet; + break; + } else if ((ch != ' ') && !Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stCtagsStart) { + if (ch == '\t') { + state = stCtagsFile; + } + } else if (state == stCtagsFile) { + if ((lineBuffer[i - 1] == '\t') && + ((ch == '/' && chNext == '^') || Is0To9(ch))) { + state = stCtags; + break; + } else if ((ch == '/') && (chNext == '^')) { + state = stCtagsStartString; + } + } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) { + state = stCtagsStringDollar; + break; + } + } + if (state == stGcc) { + return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC; + } else if ((state == stMsVc) || (state == stMsDotNet)) { + return SCE_ERR_MS; + } else if ((state == stCtagsStringDollar) || (state == stCtags)) { + return SCE_ERR_CTAG; + } else if (initialColonPart && strstr(lineBuffer, ": warning C")) { + // Microsoft warning without line number + // : warning C9999 + return SCE_ERR_MS; + } else { + return SCE_ERR_DEFAULT; + } + } +} + +#define CSI "\033[" + +constexpr bool SequenceEnd(int ch) noexcept { + return (ch == 0) || ((ch >= '@') && (ch <= '~')); +} + +int StyleFromSequence(const char *seq) noexcept { + int bold = 0; + int colour = 0; + while (!SequenceEnd(*seq)) { + if (Is0To9(*seq)) { + int base = *seq - '0'; + if (Is0To9(seq[1])) { + base = base * 10; + base += seq[1] - '0'; + seq++; + } + if (base == 0) { + colour = 0; + bold = 0; + } + else if (base == 1) { + bold = 1; + } + else if (base >= 30 && base <= 37) { + colour = base - 30; + } + } + seq++; + } + return SCE_ERR_ES_BLACK + bold * 8 + colour; +} + +void ColouriseErrorListLine( + const std::string &lineBuffer, + Sci_PositionU endPos, + Accessor &styler, + bool valueSeparate, + bool escapeSequences) { + Sci_Position startValue = -1; + const Sci_PositionU lengthLine = lineBuffer.length(); + const int style = RecogniseErrorListLine(lineBuffer.c_str(), lengthLine, startValue); + if (escapeSequences && strstr(lineBuffer.c_str(), CSI)) { + const Sci_Position startPos = endPos - lengthLine; + const char *linePortion = lineBuffer.c_str(); + Sci_Position startPortion = startPos; + int portionStyle = style; + while (const char *startSeq = strstr(linePortion, CSI)) { + if (startSeq > linePortion) { + styler.ColourTo(startPortion + (startSeq - linePortion), portionStyle); + } + const char *endSeq = startSeq + 2; + while (!SequenceEnd(*endSeq)) + endSeq++; + const Sci_Position endSeqPosition = startPortion + (endSeq - linePortion) + 1; + switch (*endSeq) { + case 0: + styler.ColourTo(endPos, SCE_ERR_ESCSEQ_UNKNOWN); + return; + case 'm': // Colour command + styler.ColourTo(endSeqPosition, SCE_ERR_ESCSEQ); + portionStyle = StyleFromSequence(startSeq+2); + break; + case 'K': // Erase to end of line -> ignore + styler.ColourTo(endSeqPosition, SCE_ERR_ESCSEQ); + break; + default: + styler.ColourTo(endSeqPosition, SCE_ERR_ESCSEQ_UNKNOWN); + portionStyle = style; + } + startPortion = endSeqPosition; + linePortion = endSeq + 1; + } + styler.ColourTo(endPos, portionStyle); + } else { + if (valueSeparate && (startValue >= 0)) { + styler.ColourTo(endPos - (lengthLine - startValue), style); + styler.ColourTo(endPos, SCE_ERR_VALUE); + } else { + styler.ColourTo(endPos, style); + } + } +} + +void ColouriseErrorListDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { + std::string lineBuffer; + styler.StartAt(startPos); + styler.StartSegment(startPos); + + // property lexer.errorlist.value.separate + // For lines in the output pane that are matches from Find in Files or GCC-style + // diagnostics, style the path and line number separately from the rest of the + // line with style 21 used for the rest of the line. + // This allows matched text to be more easily distinguished from its location. + const bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; + + // property lexer.errorlist.escape.sequences + // Set to 1 to interpret escape sequences. + const bool escapeSequences = styler.GetPropertyInt("lexer.errorlist.escape.sequences") != 0; + + for (Sci_PositionU i = startPos; i < startPos + length; i++) { + lineBuffer.push_back(styler[i]); + if (AtEOL(styler, i)) { + // End of line met, colourise it + ColouriseErrorListLine(lineBuffer, i, styler, valueSeparate, escapeSequences); + lineBuffer.clear(); + } + } + if (!lineBuffer.empty()) { // Last line does not have ending characters + ColouriseErrorListLine(lineBuffer, startPos + length - 1, styler, valueSeparate, escapeSequences); + } +} + +const char *const emptyWordListDesc[] = { + nullptr +}; + +} + +extern const LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", nullptr, emptyWordListDesc); diff --git a/src/lexilla/lexers/LexFSharp.cxx b/src/lexilla/lexers/LexFSharp.cxx new file mode 100644 index 000000000..6ffa79a5a --- /dev/null +++ b/src/lexilla/lexers/LexFSharp.cxx @@ -0,0 +1,769 @@ +/** + * @file LexFSharp.cxx + * Lexer for F# 5.0 + * Copyright (c) 2021 Robert Di Pardo + * Parts of LexerFSharp::Lex were adapted from LexCaml.cxx by Robert Roessler ("RR"). + * Parts of LexerFSharp::Fold were adapted from LexCPP.cxx by Neil Hodgson and Udo Lechner. + * The License.txt file describes the conditions under which this software may be distributed. + */ +// clang-format off +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" +// clang-format on + +using namespace Scintilla; +using namespace Lexilla; + +static const char *const lexerName = "fsharp"; +static constexpr int WORDLIST_SIZE = 5; +static const char *const fsharpWordLists[] = { + "standard language keywords", + "core functions, including those in the FSharp.Collections namespace", + "built-in types, core namespaces, modules", + "optional", + "optional", + nullptr, +}; +static constexpr int keywordClasses[] = { + SCE_FSHARP_KEYWORD, SCE_FSHARP_KEYWORD2, SCE_FSHARP_KEYWORD3, SCE_FSHARP_KEYWORD4, SCE_FSHARP_KEYWORD5, +}; + +namespace { + +struct OptionsFSharp { + bool fold = true; + bool foldCompact = true; + bool foldComment = true; + bool foldCommentStream = true; + bool foldCommentMultiLine = true; + bool foldPreprocessor = false; + bool foldImports = true; +}; + +struct OptionSetFSharp : public OptionSet { + OptionSetFSharp() { + DefineProperty("fold", &OptionsFSharp::fold); + DefineProperty("fold.compact", &OptionsFSharp::foldCompact); + DefineProperty("fold.comment", &OptionsFSharp::foldComment, + "Setting this option to 0 disables comment folding in F# files."); + + DefineProperty("fold.fsharp.comment.stream", &OptionsFSharp::foldCommentStream, + "Setting this option to 0 disables folding of ML-style comments in F# files when " + "fold.comment=1."); + + DefineProperty("fold.fsharp.comment.multiline", &OptionsFSharp::foldCommentMultiLine, + "Setting this option to 0 disables folding of grouped line comments in F# files when " + "fold.comment=1."); + + DefineProperty("fold.fsharp.preprocessor", &OptionsFSharp::foldPreprocessor, + "Setting this option to 1 enables folding of F# compiler directives."); + + DefineProperty("fold.fsharp.imports", &OptionsFSharp::foldImports, + "Setting this option to 0 disables folding of F# import declarations."); + + DefineWordListSets(fsharpWordLists); + } +}; + +struct FSharpString { + Sci_Position startPos = INVALID_POSITION; + int startChar = '"', nextChar = '\0'; + constexpr bool HasLength() const { + return startPos > INVALID_POSITION; + } + constexpr bool CanInterpolate() const { + return startChar == '$' || (startChar == '@' && nextChar == '$'); + } + constexpr bool IsVerbatim() const { + return startChar == '@' || (startChar == '$' && nextChar == '@'); + } +}; + +class UnicodeChar { + enum class Notation { none, asciiDec, asciiHex, utf16, utf32 }; + Notation type = Notation::none; + // single-byte Unicode char (000 - 255) + int asciiDigits[3] = { 0 }; + int maxDigit = '9'; + int toEnd = 0; + bool invalid = false; + +public: + UnicodeChar() noexcept = default; + explicit UnicodeChar(const int prefix) { + if (IsADigit(prefix)) { + *asciiDigits = prefix; + if (*asciiDigits >= '0' && *asciiDigits <= '2') { + type = Notation::asciiDec; + // count first digit as "prefix" + toEnd = 2; + } + } else if (prefix == 'x' || prefix == 'u' || prefix == 'U') { + switch (prefix) { + case 'x': + type = Notation::asciiHex; + toEnd = 2; + break; + case 'u': + type = Notation::utf16; + toEnd = 4; + break; + case 'U': + type = Notation::utf32; + toEnd = 8; + break; + } + } + } + void Parse(const int ch) { + invalid = false; + switch (type) { + case Notation::asciiDec: { + maxDigit = (*asciiDigits < '2') ? '9' : (asciiDigits[1] <= '4') ? '9' : '5'; + if (IsADigit(ch) && asciiDigits[1] <= maxDigit && ch <= maxDigit) { + asciiDigits[1] = ch; + toEnd--; + } else { + invalid = true; + } + break; + } + case Notation::asciiHex: + case Notation::utf16: + if (IsADigit(ch, 16)) { + toEnd--; + } else { + invalid = true; + } + break; + case Notation::utf32: + if ((toEnd > 6 && ch == '0') || (toEnd <= 6 && IsADigit(ch, 16))) { + toEnd--; + } else { + invalid = true; + } + break; + case Notation::none: + break; + } + } + constexpr bool AtEnd() noexcept { + return invalid || type == Notation::none || (type != Notation::none && toEnd < 0); + } +}; + +inline bool MatchStreamCommentStart(StyleContext &cxt) { + // match (* ... *), but allow point-free usage of the `*` operator, + // e.g. List.fold (*) 1 [ 1; 2; 3 ] + return (cxt.Match('(', '*') && cxt.GetRelative(2) != ')'); +} + +inline bool MatchStreamCommentEnd(const StyleContext &cxt) { + return (cxt.ch == ')' && cxt.chPrev == '*'); +} + +inline bool MatchLineComment(const StyleContext &cxt) { + // style shebang lines as comments in F# scripts: + // https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf#page=30&zoom=auto,-98,537 + return cxt.Match('/', '/') || cxt.Match('#', '!'); +} + +inline bool MatchLineNumberStart(StyleContext &cxt) { + return cxt.atLineStart && (cxt.MatchIgnoreCase("#line") || + (cxt.ch == '#' && (IsADigit(cxt.chNext) || IsADigit(cxt.GetRelative(2))))); +} + +inline bool MatchPPDirectiveStart(const StyleContext &cxt) { + return (cxt.atLineStart && cxt.ch == '#' && iswordstart(cxt.chNext)); +} + +inline bool MatchTypeAttributeStart(const StyleContext &cxt) { + return cxt.Match('[', '<'); +} + +inline bool MatchTypeAttributeEnd(const StyleContext &cxt) { + return (cxt.ch == ']' && cxt.chPrev == '>'); +} + +inline bool MatchQuotedExpressionStart(const StyleContext &cxt) { + return cxt.Match('<', '@'); +} + +inline bool MatchQuotedExpressionEnd(const StyleContext &cxt) { + return (cxt.ch == '>' && cxt.chPrev == '@'); +} + +inline bool MatchStringStart(StyleContext &cxt) { + return (cxt.ch == '"' || cxt.Match("@\"") || cxt.Match("$\"") || cxt.Match("@$\"") || cxt.Match("$@\"") || + cxt.Match("``")); +} + +inline bool FollowsEscapedBackslash(StyleContext &cxt) { + int count = 0; + for (Sci_Position offset = 1; cxt.GetRelative(-offset) == '\\'; offset++) + count++; + return count % 2 != 0; +} + +inline bool MatchStringEnd(StyleContext &cxt, const FSharpString &fsStr) { + return (fsStr.HasLength() && + // end of quoted identifier? + ((cxt.ch == '`' && cxt.chPrev == '`') || + // end of literal or interpolated triple-quoted string? + ((fsStr.startChar == '"' || (fsStr.CanInterpolate() && !(fsStr.IsVerbatim() || cxt.chPrev == '$'))) && + cxt.MatchIgnoreCase("\"\"\"")) || + // end of verbatim string? + (fsStr.IsVerbatim() && + // embedded quotes must be in pairs + cxt.ch == '"' && cxt.chNext != '"' && + (cxt.chPrev != '"' || + // empty verbatim string? + ((cxt.GetRelative(-2) == '@' || cxt.GetRelative(-2) == '$') || + // pair of quotes at end of string? + (cxt.GetRelative(-2) == '"' && !(cxt.GetRelative(-3) == '@' || cxt.GetRelative(-3) == '$'))))))) || + (!fsStr.HasLength() && cxt.ch == '"' && + ((cxt.chPrev != '\\' || (cxt.GetRelative(-2) == '\\' && !FollowsEscapedBackslash(cxt))) || + // treat backslashes as char literals in verbatim strings + (fsStr.IsVerbatim() && cxt.chPrev == '\\'))); +} + +inline bool MatchCharacterStart(StyleContext &cxt) { + // don't style generic type parameters: 'a, 'b, 'T, etc. + return (cxt.ch == '\'' && !(cxt.chPrev == ':' || cxt.GetRelative(-2) == ':')); +} + +inline bool CanEmbedQuotes(StyleContext &cxt) { + // allow unescaped double quotes inside literal or interpolated triple-quoted strings, verbatim strings, + // and quoted identifiers: + // - https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/strings + // - https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/interpolated-strings#syntax + // - https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf#page=25&zoom=auto,-98,600 + return cxt.Match("$\"\"\"") || cxt.Match("\"\"\"") || cxt.Match("@$\"\"\"") || cxt.Match("$@\"\"\"") || + cxt.Match('@', '"') || cxt.Match('`', '`'); +} + +inline bool IsLineEnd(StyleContext &cxt, const Sci_Position offset) { + const int ch = cxt.GetRelative(offset, '\n'); + return (ch == '\r' || ch == '\n'); +} + +class LexerFSharp : public DefaultLexer { + WordList keywords[WORDLIST_SIZE]; + OptionsFSharp options; + OptionSetFSharp optionSet; + CharacterSet setOperators; + CharacterSet setFormatSpecs; + CharacterSet setDotNetFormatSpecs; + CharacterSet setFormatFlags; + CharacterSet numericMetaChars1; + CharacterSet numericMetaChars2; + std::map numericPrefixes = { { 'b', 2 }, { 'o', 8 }, { 'x', 16 } }; + +public: + explicit LexerFSharp() + : DefaultLexer(lexerName, SCLEX_FSHARP), + setOperators(CharacterSet::setNone, "~^'-+*/%=@|&<>()[]{};,:!?"), + setFormatSpecs(CharacterSet::setNone, ".%aAbBcdeEfFgGiMoOstuxX0123456789"), + setDotNetFormatSpecs(CharacterSet::setNone, "cCdDeEfFgGnNpPxX"), + setFormatFlags(CharacterSet::setNone, ".-+0 "), + numericMetaChars1(CharacterSet::setNone, "_uU"), + numericMetaChars2(CharacterSet::setNone, "fFIlLmMnsy") { + } + LexerFSharp(const LexerFSharp &) = delete; + LexerFSharp(LexerFSharp &&) = delete; + LexerFSharp &operator=(const LexerFSharp &) = delete; + LexerFSharp &operator=(LexerFSharp &&) = delete; + static ILexer5 *LexerFactoryFSharp() { + return new LexerFSharp(); + } + virtual ~LexerFSharp() { + } + void SCI_METHOD Release() noexcept override { + delete this; + } + int SCI_METHOD Version() const noexcept override { + return lvRelease5; + } + const char *SCI_METHOD GetName() noexcept override { + return lexerName; + } + int SCI_METHOD GetIdentifier() noexcept override { + return SCLEX_FSHARP; + } + int SCI_METHOD LineEndTypesSupported() noexcept override { + return SC_LINE_END_TYPE_DEFAULT; + } + void *SCI_METHOD PrivateCall(int, void *) noexcept override { + return nullptr; + } + const char *SCI_METHOD DescribeWordListSets() override { + return optionSet.DescribeWordListSets(); + } + const char *SCI_METHOD PropertyNames() override { + return optionSet.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return optionSet.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) override { + return optionSet.DescribeProperty(name); + } + const char *SCI_METHOD PropertyGet(const char *key) override { + return optionSet.PropertyGet(key); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override { + if (optionSet.PropertySet(&options, key, val)) { + return 0; + } + return INVALID_POSITION; + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU start, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU start, Sci_Position length, int initStyle,IDocument *pAccess) override; + +private: + inline bool IsNumber(StyleContext &cxt, const int base = 10) { + return IsADigit(cxt.ch, base) || (IsADigit(cxt.chPrev, base) && numericMetaChars1.Contains(cxt.ch)) || + (IsADigit(cxt.GetRelative(-2), base) && numericMetaChars2.Contains(cxt.ch)); + } + + inline bool IsFloat(StyleContext &cxt) { + if (cxt.MatchIgnoreCase("e+") || cxt.MatchIgnoreCase("e-")) { + cxt.Forward(); + return true; + } + return ((cxt.chPrev == '.' && IsADigit(cxt.ch)) || + (IsADigit(cxt.chPrev) && (cxt.ch == '.' || numericMetaChars2.Contains(cxt.ch)))); + } +}; + +Sci_Position SCI_METHOD LexerFSharp::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + Sci_Position firstModification = INVALID_POSITION; + + if (n < WORDLIST_SIZE) { + wordListN = &keywords[n]; + } + if (wordListN && wordListN->Set(wl)) { + firstModification = 0; + } + return firstModification; +} + +void SCI_METHOD LexerFSharp::Lex(Sci_PositionU start, Sci_Position length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + StyleContext sc(start, static_cast(length), initStyle, styler); + Sci_Position lineCurrent = styler.GetLine(static_cast(start)); + Sci_PositionU cursor = 0; + UnicodeChar uniCh = UnicodeChar(); + FSharpString fsStr = FSharpString(); + constexpr Sci_Position MAX_WORD_LEN = 64; + constexpr int SPACE = ' '; + int currentBase = 10; + int levelNesting = (lineCurrent >= 1) ? styler.GetLineState(lineCurrent - 1) : 0; + bool isInterpolated = false; + + while (sc.More()) { + Sci_PositionU colorSpan = sc.currentPos - 1; + int state = -1; + bool advance = true; + + switch (sc.state & 0xff) { + case SCE_FSHARP_DEFAULT: + cursor = sc.currentPos; + + if (MatchLineNumberStart(sc)) { + state = SCE_FSHARP_LINENUM; + } else if (MatchPPDirectiveStart(sc)) { + state = SCE_FSHARP_PREPROCESSOR; + } else if (MatchLineComment(sc)) { + state = SCE_FSHARP_COMMENTLINE; + sc.Forward(); + sc.ch = SPACE; + } else if (MatchStreamCommentStart(sc)) { + state = SCE_FSHARP_COMMENT; + sc.Forward(); + sc.ch = SPACE; + } else if (MatchTypeAttributeStart(sc)) { + state = SCE_FSHARP_ATTRIBUTE; + sc.Forward(); + } else if (MatchQuotedExpressionStart(sc)) { + state = SCE_FSHARP_QUOTATION; + sc.Forward(); + } else if (MatchCharacterStart(sc)) { + state = SCE_FSHARP_CHARACTER; + } else if (MatchStringStart(sc)) { + fsStr.startChar = sc.ch; + fsStr.nextChar = sc.chNext; + fsStr.startPos = INVALID_POSITION; + if (CanEmbedQuotes(sc)) { + // double quotes after this position should be non-terminating + fsStr.startPos = static_cast(sc.currentPos - cursor); + } + if (sc.ch == '`') { + state = SCE_FSHARP_QUOT_IDENTIFIER; + } else if (fsStr.IsVerbatim()) { + state = SCE_FSHARP_VERBATIM; + } else { + state = SCE_FSHARP_STRING; + } + } else if (IsADigit(sc.ch, currentBase) || + ((sc.ch == '+' || sc.ch == '-') && IsADigit(sc.chNext))) { + state = SCE_FSHARP_NUMBER; + } else if (setOperators.Contains(sc.ch) && + // don't use operator style in async keywords (e.g. `return!`) + !(sc.ch == '!' && iswordstart(sc.chPrev)) && + // don't use operator style in member access, array/string indexing + !(sc.ch == '.' && (sc.chPrev == '\"' || iswordstart(sc.chPrev)) && + (iswordstart(sc.chNext) || sc.chNext == '['))) { + state = SCE_FSHARP_OPERATOR; + } else if (iswordstart(sc.ch)) { + state = SCE_FSHARP_IDENTIFIER; + } else { + state = SCE_FSHARP_DEFAULT; + } + break; + case SCE_FSHARP_LINENUM: + case SCE_FSHARP_PREPROCESSOR: + case SCE_FSHARP_COMMENTLINE: + if (sc.MatchLineEnd()) { + state = SCE_FSHARP_DEFAULT; + advance = false; + } + break; + case SCE_FSHARP_COMMENT: + if (MatchStreamCommentStart(sc)) { + sc.Forward(); + sc.ch = SPACE; + levelNesting++; + } else if (MatchStreamCommentEnd(sc)) { + if (levelNesting > 0) + levelNesting--; + else { + state = SCE_FSHARP_DEFAULT; + colorSpan++; + } + } + break; + case SCE_FSHARP_ATTRIBUTE: + case SCE_FSHARP_QUOTATION: + if (MatchTypeAttributeEnd(sc) || MatchQuotedExpressionEnd(sc)) { + state = SCE_FSHARP_DEFAULT; + colorSpan++; + } + break; + case SCE_FSHARP_CHARACTER: + if (sc.chPrev == '\\' && sc.GetRelative(-2) != '\\') { + uniCh = UnicodeChar(sc.ch); + } else if (sc.ch == '\'' && + ((sc.chPrev == ' ' && sc.GetRelative(-2) == '\'') || sc.chPrev != '\\' || + (sc.chPrev == '\\' && sc.GetRelative(-2) == '\\'))) { + // byte literal? + if (sc.Match('\'', 'B')) { + sc.Forward(); + colorSpan++; + } + if (!sc.atLineEnd) { + colorSpan++; + } else { + sc.ChangeState(SCE_FSHARP_IDENTIFIER); + } + state = SCE_FSHARP_DEFAULT; + } else { + uniCh.Parse(sc.ch); + if (uniCh.AtEnd() && (sc.currentPos - cursor) >= 2) { + // terminate now, since we left the char behind + sc.ChangeState(SCE_FSHARP_IDENTIFIER); + advance = false; + } + } + break; + case SCE_FSHARP_STRING: + case SCE_FSHARP_VERBATIM: + case SCE_FSHARP_QUOT_IDENTIFIER: + if (MatchStringEnd(sc, fsStr)) { + const Sci_Position strLen = static_cast(sc.currentPos - cursor); + // backtrack to start of string + for (Sci_Position i = -strLen; i < 0; i++) { + const int startQuote = sc.GetRelative(i); + if (startQuote == '\"' || (startQuote == '`' && sc.GetRelative(i - 1) == '`')) { + // byte array? + if (sc.Match('\"', 'B')) { + sc.Forward(); + colorSpan++; + } + if (!sc.atLineEnd) { + colorSpan++; + } else { + sc.ChangeState(SCE_FSHARP_IDENTIFIER); + } + state = SCE_FSHARP_DEFAULT; + break; + } + } + } else if (sc.ch == '%' && + !(fsStr.startChar == '`' || sc.MatchIgnoreCase("% ") || sc.MatchIgnoreCase("% \"")) && + (setFormatSpecs.Contains(sc.chNext) || setFormatFlags.Contains(sc.chNext))) { + if (fsStr.CanInterpolate() && sc.chNext != '%') { + for (Sci_Position i = 2; i < length && !IsLineEnd(sc, i); i++) { + if (sc.GetRelative(i) == '{') { + state = setFormatSpecs.Contains(sc.GetRelative(i - 1)) + ? SCE_FSHARP_FORMAT_SPEC + : state; + break; + } + } + } else { + state = SCE_FSHARP_FORMAT_SPEC; + } + } else if (isInterpolated) { + if (sc.ch == ',') { + // .NET alignment specifier? + state = (sc.chNext == '+' || sc.chNext == '-' || IsADigit(sc.chNext)) + ? SCE_FSHARP_FORMAT_SPEC + : state; + } else if (sc.ch == ':') { + // .NET format specifier? + state = setDotNetFormatSpecs.Contains(sc.chNext) + ? SCE_FSHARP_FORMAT_SPEC + : state; + } else if (sc.chNext == '}') { + isInterpolated = false; + sc.Forward(); + state = fsStr.IsVerbatim() ? SCE_FSHARP_VERBATIM : SCE_FSHARP_STRING; + } + } else if (fsStr.CanInterpolate() && sc.ch == '{') { + isInterpolated = true; + } + break; + case SCE_FSHARP_IDENTIFIER: + if (!(iswordstart(sc.ch) || sc.ch == '\'')) { + const Sci_Position wordLen = static_cast(sc.currentPos - cursor); + if (wordLen < MAX_WORD_LEN) { + // wordLength is believable as keyword, [re-]construct token - RR + char token[MAX_WORD_LEN] = { 0 }; + for (Sci_Position i = -wordLen; i < 0; i++) { + token[wordLen + i] = static_cast(sc.GetRelative(i)); + } + token[wordLen] = '\0'; + // a snake_case_identifier can never be a keyword + if (!(sc.ch == '_' || sc.GetRelative(-wordLen - 1) == '_')) { + for (int i = 0; i < WORDLIST_SIZE; i++) { + if (keywords[i].InList(token)) { + sc.ChangeState(keywordClasses[i]); + break; + } + } + } + } + state = SCE_FSHARP_DEFAULT; + advance = false; + } + break; + case SCE_FSHARP_OPERATOR: + // special-case "()" and "[]" tokens as KEYWORDS - RR + if ((sc.ch == ')' && sc.chPrev == '(') || (sc.ch == ']' && sc.chPrev == '[')) { + sc.ChangeState(SCE_FSHARP_KEYWORD); + colorSpan++; + } else { + advance = false; + } + state = SCE_FSHARP_DEFAULT; + break; + case SCE_FSHARP_NUMBER: + if ((setOperators.Contains(sc.chPrev) || IsASpaceOrTab(sc.chPrev)) && sc.ch == '0') { + if (numericPrefixes.find(sc.chNext) != numericPrefixes.end()) { + currentBase = numericPrefixes[sc.chNext]; + sc.Forward(2); + } + } else if ((setOperators.Contains(sc.GetRelative(-2)) || IsASpaceOrTab(sc.GetRelative(-2))) && + sc.chPrev == '0') { + if (numericPrefixes.find(sc.ch) != numericPrefixes.end()) { + currentBase = numericPrefixes[sc.ch]; + sc.Forward(); + } + } + state = (IsNumber(sc, currentBase) || IsFloat(sc)) + ? SCE_FSHARP_NUMBER + // change style even when operators aren't spaced + : setOperators.Contains(sc.ch) ? SCE_FSHARP_OPERATOR : SCE_FSHARP_DEFAULT; + currentBase = (state == SCE_FSHARP_NUMBER) ? currentBase : 10; + break; + case SCE_FSHARP_FORMAT_SPEC: + if (!(isInterpolated && IsADigit(sc.chNext)) && + (!setFormatSpecs.Contains(sc.chNext) || + !(setFormatFlags.Contains(sc.ch) || IsADigit(sc.ch)) || + (setFormatFlags.Contains(sc.ch) && sc.ch == sc.chNext))) { + colorSpan++; + state = fsStr.IsVerbatim() ? SCE_FSHARP_VERBATIM : SCE_FSHARP_STRING; + } + break; + } + + if (sc.MatchLineEnd()) { + styler.SetLineState(lineCurrent++, (sc.state == SCE_FSHARP_COMMENT) ? levelNesting : 0); + advance = true; + } + + if (state >= SCE_FSHARP_DEFAULT) { + styler.ColourTo(colorSpan, sc.state); + sc.ChangeState(state); + } + + if (advance) { + sc.Forward(); + } + } + + sc.Complete(); +} + +bool LineContains(LexAccessor &styler, const char *word, const Sci_Position start, + const int chAttr = SCE_FSHARP_DEFAULT); + +void FoldLexicalGroup(LexAccessor &styler, int &levelNext, const Sci_Position lineCurrent, const char *word, + const int chAttr); + +void SCI_METHOD LexerFSharp::Fold(Sci_PositionU start, Sci_Position length, int initStyle, IDocument *pAccess) { + if (!options.fold) { + return; + } + + LexAccessor styler(pAccess); + const Sci_Position startPos = static_cast(start); + const Sci_PositionU endPos = start + length; + Sci_Position lineCurrent = styler.GetLine(startPos); + Sci_Position lineNext = lineCurrent + 1; + Sci_Position lineStartNext = styler.LineStart(lineNext); + int style = initStyle; + int styleNext = styler.StyleAt(startPos); + char chNext = styler[startPos]; + int levelNext; + int levelCurrent = SC_FOLDLEVELBASE; + int visibleChars = 0; + + if (lineCurrent > 0) { + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 0x10; + } + + levelNext = levelCurrent; + + for (Sci_PositionU i = start; i < endPos; i++) { + const Sci_Position currentPos = static_cast(i); + const bool atEOL = (currentPos == (lineStartNext - 1) || styler.SafeGetCharAt(currentPos) == '\r'); + const bool atLineOrDocEnd = (atEOL || (i == (endPos - 1))); + const int stylePrev = style; + const char ch = chNext; + const bool inLineComment = (stylePrev == SCE_FSHARP_COMMENTLINE); + style = styleNext; + styleNext = styler.StyleAt(currentPos + 1); + chNext = styler.SafeGetCharAt(currentPos + 1); + + if (options.foldComment) { + if (options.foldCommentMultiLine && inLineComment && atEOL) { + FoldLexicalGroup(styler, levelNext, lineCurrent, "//", SCE_FSHARP_COMMENTLINE); + } + + if (options.foldCommentStream && style == SCE_FSHARP_COMMENT && !inLineComment) { + if (stylePrev != SCE_FSHARP_COMMENT || + (styler.Match(currentPos, "(*") && + !LineContains(styler, "*)", currentPos + 2, SCE_FSHARP_COMMENT))) { + levelNext++; + } else if ((styleNext != SCE_FSHARP_COMMENT || + ((styler.Match(currentPos, "*)") && + !LineContains(styler, "(*", styler.LineStart(lineCurrent), SCE_FSHARP_COMMENT)) && + styler.GetLineState(lineCurrent - 1) > 0)) && + !atEOL) { + levelNext--; + } + } + } + + if (options.foldPreprocessor && style == SCE_FSHARP_PREPROCESSOR) { + if (styler.Match(currentPos, "#if")) { + levelNext++; + } else if (styler.Match(currentPos, "#endif")) { + levelNext--; + } + } + + if (options.foldImports && styler.Match(currentPos, "open ") && styleNext == SCE_FSHARP_KEYWORD) { + FoldLexicalGroup(styler, levelNext, lineCurrent, "open ", SCE_FSHARP_KEYWORD); + } + + if (!IsASpace(ch)) { + visibleChars++; + } + + if (atLineOrDocEnd) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + + if (visibleChars == 0 && options.foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + + visibleChars = 0; + lineCurrent++; + lineNext = lineCurrent + 1; + lineStartNext = styler.LineStart(lineNext); + levelCurrent = levelNext; + + if (atEOL && (currentPos == (styler.Length() - 1))) { + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + } + } +} + +bool LineContains(LexAccessor &styler, const char *word, const Sci_Position start, const int chAttr) { + bool found = false; + bool requireStyle = (chAttr > SCE_FSHARP_DEFAULT); + for (Sci_Position i = start; i < styler.LineStart(styler.GetLine(start) + 1) - 1; i++) { + if (styler.Match(i, word)) { + found = requireStyle ? styler.StyleAt(i) == chAttr : true; + break; + } + } + return found; +} + +void FoldLexicalGroup(LexAccessor &styler, int &levelNext, const Sci_Position lineCurrent, const char *word, + const int chAttr) { + const Sci_Position linePrev = styler.LineStart(lineCurrent - 1); + const Sci_Position lineNext = styler.LineStart(lineCurrent + 1); + const bool follows = (lineCurrent > 0) && LineContains(styler, word, linePrev, chAttr); + const bool isFollowed = LineContains(styler, word, lineNext, chAttr); + + if (isFollowed && !follows) { + levelNext++; + } else if (!isFollowed && follows && levelNext > SC_FOLDLEVELBASE) { + levelNext--; + } +} +} // namespace + +extern const LexerModule lmFSharp(SCLEX_FSHARP, LexerFSharp::LexerFactoryFSharp, "fsharp", fsharpWordLists); diff --git a/src/lexilla/lexers/LexFlagship.cxx b/src/lexilla/lexers/LexFlagship.cxx new file mode 100644 index 000000000..aa019246a --- /dev/null +++ b/src/lexilla/lexers/LexFlagship.cxx @@ -0,0 +1,355 @@ +// Scintilla source code edit control +/** @file LexFlagship.cxx + ** Lexer for Harbour and FlagShip. + ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.) + **/ +// Copyright 2005 by Randy Butler +// Copyright 2010 by Xavi (Harbour) +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) +{ + return ch >= 0x80 || + (isalnum(ch) || ch == '_'); +} + +static void ColouriseFlagShipDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + + // property lexer.flagship.styling.within.preprocessor + // For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the + // initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code. + bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0; + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + int visibleChars = 0; + int closeStringChar = 0; + int styleBeforeDCKeyword = SCE_FS_DEFAULT; + bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_FS_OPERATOR: + case SCE_FS_OPERATOR_C: + case SCE_FS_WORDOPERATOR: + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + break; + case SCE_FS_IDENTIFIER: + case SCE_FS_IDENTIFIER_C: + if (!IsAWordChar(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C); + } else if (keywords2.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C); + } else if (bEnableCode && keywords3.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD3); + } else if (bEnableCode && keywords4.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD4); + }// Else, it is really an identifier... + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_NUMBER: + if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_NUMBER_C: + if (!IsAWordChar(sc.ch) && sc.ch != '.') { + sc.SetState(SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_CONSTANT: + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_STRING: + case SCE_FS_STRING_C: + if (sc.ch == closeStringChar) { + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.atLineEnd) { + sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C); + } + break; + case SCE_FS_STRINGEOL: + case SCE_FS_STRINGEOL_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_COMMENTDOC: + case SCE_FS_COMMENTDOC_C: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENT: + case SCE_FS_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_COMMENTLINEDOC: + case SCE_FS_COMMENTLINEDOC_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) && + sc.Match('*', '/')) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_FS_PREPROCESSOR: + case SCE_FS_PREPROCESSOR_C: + if (sc.atLineEnd) { + if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (stylingWithinPreprocessor) { + if (IsASpaceOrTab(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_DISABLEDCODE: + if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } + break; + case SCE_FS_DATE: + if (sc.ch == '}') { + sc.ForwardSetState(SCE_FS_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_FS_STRINGEOL); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) { + if (bEnableCode && + (sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(4); + } else if (bEnableCode && sc.MatchIgnoreCase(".or.")) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(3); + } else if (bEnableCode && + (sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") || + (!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) { + sc.SetState(SCE_FS_CONSTANT); + sc.Forward(2); + } else if (sc.Match('/', '*')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.Match('&', '&')) { + sc.SetState(SCE_FS_COMMENTLINE); + sc.Forward(); + } else if (sc.Match('/', '/')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.ch == '*' && visibleChars == 0) { + sc.SetState(SCE_FS_COMMENT); + } else if (sc.ch == '\"' || sc.ch == '\'') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + closeStringChar = sc.ch; + } else if (closeStringChar == '>' && sc.ch == '<') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + } else if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.atLineEnd) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.MatchIgnoreCase("include")) { + if (stylingWithinPreprocessor) { + closeStringChar = '>'; + } + } else if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) { + bEnableCode = false; + if (stylingWithinPreprocessor) { + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(8); + sc.ForwardSetState(SCE_FS_DEFAULT_C); + } else { + sc.SetState(SCE_FS_DISABLEDCODE); + } + } else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } + } + } else if (bEnableCode && sc.ch == '{') { + Sci_Position p = 0; + int chSeek; + Sci_PositionU endPos(startPos + length); + do { // Skip whitespace + chSeek = sc.GetRelative(++p); + } while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos)); + if (chSeek == '^') { + sc.SetState(SCE_FS_DATE); + } else { + sc.SetState(SCE_FS_OPERATOR); + } + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C); + } else if (isoperator(static_cast(sc.ch)) || (bEnableCode && sc.ch == '@')) { + sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C); + } + } + + if (sc.atLineEnd) { + visibleChars = 0; + closeStringChar = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldFlagShipDoc(Sci_PositionU startPos, Sci_Position length, int, + WordList *[], Accessor &styler) +{ + + Sci_Position endPos = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + Sci_Position lineCurrent = styler.GetLine(startPos); + if (startPos > 0 && lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); + char chNext = styler[startPos]; + for (Sci_Position i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos-1)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static const char * const FSWordListDesc[] = { + "Keywords Commands", + "Std Library Functions", + "Procedure, return, exit", + "Class (oop)", + "Doxygen keywords", + 0 +}; + +extern const LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc); diff --git a/src/lexilla/lexers/LexForth.cxx b/src/lexilla/lexers/LexForth.cxx new file mode 100644 index 000000000..304a111c8 --- /dev/null +++ b/src/lexilla/lexers/LexForth.cxx @@ -0,0 +1,171 @@ +// Scintilla source code edit control +/** @file LexForth.cxx + ** Lexer for FORTH + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +static inline bool IsANumChar(int ch) { + return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' ); +} + +static inline bool IsASpaceChar(int ch) { + return (ch < 0x80) && isspace(ch); +} + +static void ColouriseForthDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordLists[], + Accessor &styler) { + + WordList &control = *keywordLists[0]; + WordList &keyword = *keywordLists[1]; + WordList &defword = *keywordLists[2]; + WordList &preword1 = *keywordLists[3]; + WordList &preword2 = *keywordLists[4]; + WordList &strings = *keywordLists[5]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // Determine if the current state should terminate. + if (sc.state == SCE_FORTH_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_COMMENT_ML) { + if (sc.ch == ')') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) { + // handle numbers here too, because what we thought was a number might + // turn out to be a keyword e.g. 2DUP + if (IsASpaceChar(sc.ch) ) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT; + if (control.InList(s)) { + sc.ChangeState(SCE_FORTH_CONTROL); + } else if (keyword.InList(s)) { + sc.ChangeState(SCE_FORTH_KEYWORD); + } else if (defword.InList(s)) { + sc.ChangeState(SCE_FORTH_DEFWORD); + } else if (preword1.InList(s)) { + sc.ChangeState(SCE_FORTH_PREWORD1); + } else if (preword2.InList(s)) { + sc.ChangeState(SCE_FORTH_PREWORD2); + } else if (strings.InList(s)) { + sc.ChangeState(SCE_FORTH_STRING); + newState = SCE_FORTH_STRING; + } + sc.SetState(newState); + } + if (sc.state == SCE_FORTH_NUMBER) { + if (IsASpaceChar(sc.ch)) { + sc.SetState(SCE_FORTH_DEFAULT); + } else if (!IsANumChar(sc.ch)) { + sc.ChangeState(SCE_FORTH_IDENTIFIER); + } + } + }else if (sc.state == SCE_FORTH_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_LOCALE) { + if (sc.ch == '}') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_DEFWORD) { + if (IsASpaceChar(sc.ch)) { + sc.SetState(SCE_FORTH_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_FORTH_DEFAULT) { + if (sc.ch == '\\'){ + sc.SetState(SCE_FORTH_COMMENT); + } else if (sc.ch == '(' && + (sc.atLineStart || IsASpaceChar(sc.chPrev)) && + (sc.atLineEnd || IsASpaceChar(sc.chNext))) { + sc.SetState(SCE_FORTH_COMMENT_ML); + } else if ( (sc.ch == '$' && (IsASCII(sc.chNext) && isxdigit(sc.chNext))) ) { + // number starting with $ is a hex number + sc.SetState(SCE_FORTH_NUMBER); + while(sc.More() && IsASCII(sc.chNext) && isxdigit(sc.chNext)) + sc.Forward(); + } else if ( (sc.ch == '%' && (IsASCII(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) { + // number starting with % is binary + sc.SetState(SCE_FORTH_NUMBER); + while(sc.More() && IsASCII(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1')) + sc.Forward(); + } else if ( IsASCII(sc.ch) && + (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && IsASCII(sc.chNext) && isxdigit(sc.chNext)) ) + ){ + sc.SetState(SCE_FORTH_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_FORTH_IDENTIFIER); + } else if (sc.ch == '{') { + sc.SetState(SCE_FORTH_LOCALE); + } else if (sc.ch == ':' && IsASCII(sc.chNext) && isspace(sc.chNext)) { + // highlight word definitions e.g. : GCD ( n n -- n ) ..... ; + // ^ ^^^ + sc.SetState(SCE_FORTH_DEFWORD); + while(sc.More() && IsASCII(sc.chNext) && isspace(sc.chNext)) + sc.Forward(); + } else if (sc.ch == ';' && + (sc.atLineStart || IsASpaceChar(sc.chPrev)) && + (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) { + // mark the ';' that ends a word + sc.SetState(SCE_FORTH_DEFWORD); + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + } + + } + sc.Complete(); +} + +static void FoldForthDoc(Sci_PositionU, Sci_Position, int, WordList *[], + Accessor &) { +} + +static const char * const forthWordLists[] = { + "control keywords", + "keywords", + "definition words", + "prewords with one argument", + "prewords with two arguments", + "string definition keywords", + 0, + }; + +extern const LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists); + + diff --git a/src/lexilla/lexers/LexFortran.cxx b/src/lexilla/lexers/LexFortran.cxx new file mode 100644 index 000000000..b1946927f --- /dev/null +++ b/src/lexilla/lexers/LexFortran.cxx @@ -0,0 +1,724 @@ +// Scintilla source code edit control +/** @file LexFortran.cxx + ** Lexer for Fortran. + ** Written by Chuan-jian Shen, Last changed Sep. 2003 + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +/***************************************/ +#include +#include +#include +#include +#include +#include + +#include +#include +/***************************************/ +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +/***************************************/ + +using namespace Lexilla; + +/***********************************************/ +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%'); +} +/**********************************************/ +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch)); +} +/***************************************/ +static inline bool IsABlank(unsigned int ch) { + return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ; +} +/***************************************/ +static inline bool IsALineEnd(char ch) { + return ((ch == '\n') || (ch == '\r')) ; +} +/***************************************/ +static Sci_PositionU GetContinuedPos(Sci_PositionU pos, Accessor &styler) { + while (!IsALineEnd(styler.SafeGetCharAt(pos++))) continue; + if (styler.SafeGetCharAt(pos) == '\n') pos++; + while (IsABlank(styler.SafeGetCharAt(pos++))) continue; + char chCur = styler.SafeGetCharAt(pos); + if (chCur == '&') { + while (IsABlank(styler.SafeGetCharAt(++pos))) continue; + return pos; + } else { + return pos; + } +} +/***************************************/ +static void ColouriseFortranDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler, bool isFixFormat) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + /***************************************/ + Sci_Position posLineStart = 0; + int numNonBlank = 0, prevState = 0; + Sci_Position endPos = startPos + length; + /***************************************/ + // backtrack to the nearest keyword + while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_F_WORD)) { + startPos--; + } + startPos = styler.LineStart(styler.GetLine(startPos)); + initStyle = styler.StyleAt(startPos - 1); + StyleContext sc(startPos, endPos-startPos, initStyle, styler); + /***************************************/ + for (; sc.More(); sc.Forward()) { + // remember the start position of the line + if (sc.atLineStart) { + posLineStart = sc.currentPos; + numNonBlank = 0; + sc.SetState(SCE_F_DEFAULT); + } + if (!IsASpaceOrTab(sc.ch)) numNonBlank ++; + /***********************************************/ + // Handle the fix format generically + Sci_Position toLineStart = sc.currentPos - posLineStart; + if (isFixFormat && (toLineStart < 6 || toLineStart >= 72)) { + if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') { + if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") || + sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") || + sc.MatchIgnoreCase("cms$") || sc.MatchIgnoreCase("*ms$") || sc.MatchIgnoreCase("!ms$") || + sc.chNext == '$') { + sc.SetState(SCE_F_PREPROCESSOR); + } else { + sc.SetState(SCE_F_COMMENT); + } + + while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end + } else if (toLineStart >= 72) { + sc.SetState(SCE_F_COMMENT); + while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end + } else if (toLineStart < 5) { + if (IsADigit(sc.ch)) + sc.SetState(SCE_F_LABEL); + else + sc.SetState(SCE_F_DEFAULT); + } else if (toLineStart == 5) { + //if (!IsASpace(sc.ch) && sc.ch != '0') { + if (sc.ch != '\r' && sc.ch != '\n') { + sc.SetState(SCE_F_CONTINUATION); + if (!IsASpace(sc.ch) && sc.ch != '0') + sc.ForwardSetState(prevState); + } else + sc.SetState(SCE_F_DEFAULT); + } + continue; + } + /***************************************/ + // Handle line continuation generically. + if (!isFixFormat && sc.ch == '&' && sc.state != SCE_F_COMMENT) { + char chTemp = ' '; + Sci_Position j = 1; + while (IsABlank(chTemp) && j<132) { + chTemp = static_cast(sc.GetRelative(j)); + j++; + } + if (chTemp == '!') { + sc.SetState(SCE_F_CONTINUATION); + if (sc.chNext == '!') sc.ForwardSetState(SCE_F_COMMENT); + } else if (chTemp == '\r' || chTemp == '\n') { + int currentState = sc.state; + sc.SetState(SCE_F_CONTINUATION); + sc.ForwardSetState(SCE_F_DEFAULT); + while (IsASpace(sc.ch) && sc.More()) { + sc.Forward(); + if (sc.atLineStart) numNonBlank = 0; + if (!IsASpaceOrTab(sc.ch)) numNonBlank ++; + } + if (sc.ch == '&') { + sc.SetState(SCE_F_CONTINUATION); + sc.Forward(); + } + sc.SetState(currentState); + } + } + /***************************************/ + // Hanndle preprocessor directives + if (sc.ch == '#' && numNonBlank == 1) + { + sc.SetState(SCE_F_PREPROCESSOR); + while (!sc.atLineEnd && sc.More()) + sc.Forward(); // Until line end + } + /***************************************/ + // Determine if the current state should terminate. + if (sc.state == SCE_F_OPERATOR) { + sc.SetState(SCE_F_DEFAULT); + } else if (sc.state == SCE_F_NUMBER) { + if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) { + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '%')) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_F_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_F_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_F_WORD3); + } + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_COMMENT || sc.state == SCE_F_PREPROCESSOR) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_STRING1) { + prevState = sc.state; + if (sc.ch == '\'') { + if (sc.chNext == '\'') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_F_DEFAULT); + prevState = SCE_F_DEFAULT; + } + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_F_STRINGEOL); + sc.ForwardSetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_STRING2) { + prevState = sc.state; + if (sc.atLineEnd) { + sc.ChangeState(SCE_F_STRINGEOL); + sc.ForwardSetState(SCE_F_DEFAULT); + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_F_DEFAULT); + prevState = SCE_F_DEFAULT; + } + } + } else if (sc.state == SCE_F_OPERATOR2) { + if (sc.ch == '.') { + sc.ForwardSetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_CONTINUATION) { + sc.SetState(SCE_F_DEFAULT); + } else if (sc.state == SCE_F_LABEL) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_F_DEFAULT); + } else { + if (isFixFormat && sc.currentPos-posLineStart > 4) + sc.SetState(SCE_F_DEFAULT); + else if (numNonBlank > 5) + sc.SetState(SCE_F_DEFAULT); + } + } + /***************************************/ + // Determine if a new state should be entered. + if (sc.state == SCE_F_DEFAULT) { + if (sc.ch == '!') { + if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") || + sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') { + sc.SetState(SCE_F_PREPROCESSOR); + } else { + sc.SetState(SCE_F_COMMENT); + } + } else if ((!isFixFormat) && IsADigit(sc.ch) && numNonBlank == 1) { + sc.SetState(SCE_F_LABEL); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_F_NUMBER); + } else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' || + tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) { + sc.SetState(SCE_F_NUMBER); + sc.Forward(); + } else if (sc.ch == '.' && isalpha(sc.chNext)) { + sc.SetState(SCE_F_OPERATOR2); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_F_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_F_STRING2); + } else if (sc.ch == '\'') { + sc.SetState(SCE_F_STRING1); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_F_OPERATOR); + } + } + } + sc.Complete(); +} +/***************************************/ +static void CheckLevelCommentLine(const unsigned int nComL, + Sci_Position nComColB[], Sci_Position nComColF[], Sci_Position &nComCur, + bool comLineB[], bool comLineF[], bool &comLineCur, + int &levelDeltaNext) { + levelDeltaNext = 0; + if (!comLineCur) { + return; + } + + if (!comLineF[0] || nComColF[0] != nComCur) { + unsigned int i=0; + for (; i= nLineTotal) { + return; + } + + for (int i=nComL-2; i>=0; i--) { + nComColB[i+1] = nComColB[i]; + comLineB[i+1] = comLineB[i]; + } + nComColB[0] = nComCur; + comLineB[0] = comLineCur; + nComCur = nComColF[0]; + comLineCur = comLineF[0]; + for (unsigned int i=0; i+1 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + isPrevLine = true; + } else { + isPrevLine = false; + } + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + int levelDeltaNext = 0; + + const unsigned int nComL = 3; // defines how many comment lines should be before they are folded + Sci_Position nComColB[nComL] = {}; + Sci_Position nComColF[nComL] = {}; + Sci_Position nComCur = 0; + bool comLineB[nComL] = {}; + bool comLineF[nComL] = {}; + bool comLineCur; + Sci_Position nLineTotal = styler.GetLine(styler.Length()-1) + 1; + if (foldComment) { + for (unsigned int i=0; i= nLineTotal) { + comLineF[i] = false; + break; + } + GetIfLineComment(styler, isFixFormat, chL, comLineF[i], nComColF[i]); + } + GetIfLineComment(styler, isFixFormat, lineCurrent, comLineCur, nComCur); + CheckBackComLines(styler, isFixFormat, lineCurrent, nComL, nComColB, nComColF, nComCur, + comLineB, comLineF, comLineCur); + } + int levelCurrent = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + + /***************************************/ + Sci_Position lastStart = 0; + char prevWord[32] = ""; + /***************************************/ + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + char chNextNonBlank = chNext; + bool nextEOL = false; + if (IsALineEnd(chNextNonBlank)) { + nextEOL = true; + } + Sci_PositionU j=i+1; + while(IsABlank(chNextNonBlank) && j(tolower(styler[lastStart+k])); + } + s[k] = '\0'; + // Handle the forall and where statement and structure. + if (strcmp(s, "forall") == 0 || (strcmp(s, "where") == 0 && strcmp(prevWord, "else") != 0)) { + if (strcmp(prevWord, "end") != 0) { + j = i + 1; + char chBrace = '(', chSeek = ')', ch1 = styler.SafeGetCharAt(j); + // Find the position of the first ( + while (ch1 != chBrace && j 0) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + levelCurrent += levelDeltaNext; + levelDeltaNext = 0; + visibleChars = 0; + strcpy(prevWord, ""); + isPrevLine = false; + + if (foldComment) { + StepCommentLine(styler, isFixFormat, lineCurrent, nComL, nComColB, nComColF, nComCur, + comLineB, comLineF, comLineCur); + } + } + /***************************************/ + if (!isspacechar(ch)) visibleChars++; + } + /***************************************/ +} +/***************************************/ +static const char * const FortranWordLists[] = { + "Primary keywords and identifiers", + "Intrinsic functions", + "Extended and user defined functions", + 0, +}; +/***************************************/ +static void ColouriseFortranDocFreeFormat(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, false); +} +/***************************************/ +static void ColouriseFortranDocFixFormat(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, true); +} +/***************************************/ +static void FoldFortranDocFreeFormat(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *[], Accessor &styler) { + FoldFortranDoc(startPos, length, initStyle,styler, false); +} +/***************************************/ +static void FoldFortranDocFixFormat(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *[], Accessor &styler) { + FoldFortranDoc(startPos, length, initStyle,styler, true); +} +/***************************************/ +extern const LexerModule lmFortran(SCLEX_FORTRAN, ColouriseFortranDocFreeFormat, "fortran", FoldFortranDocFreeFormat, FortranWordLists); +extern const LexerModule lmF77(SCLEX_F77, ColouriseFortranDocFixFormat, "f77", FoldFortranDocFixFormat, FortranWordLists); diff --git a/src/lexilla/lexers/LexGAP.cxx b/src/lexilla/lexers/LexGAP.cxx new file mode 100644 index 000000000..45a386fe9 --- /dev/null +++ b/src/lexilla/lexers/LexGAP.cxx @@ -0,0 +1,267 @@ +// Scintilla source code edit control +/** @file LexGAP.cxx + ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra) + ** http://www.gap-system.org + **/ +// Copyright 2007 by Istvan Szollosi ( szteven gmail com ) +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsGAPOperator(char ch) { + if (IsASCII(ch) && isalnum(ch)) return false; + if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '^' || ch == ',' || ch == '!' || ch == '.' || + ch == '=' || ch == '<' || ch == '>' || ch == '(' || + ch == ')' || ch == ';' || ch == '[' || ch == ']' || + ch == '{' || ch == '}' || ch == ':' ) + return true; + return false; +} + +static void GetRange(Sci_PositionU start, Sci_PositionU end, Accessor &styler, char *s, Sci_PositionU len) { + Sci_PositionU i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(styler[start + i]); + i++; + } + s[i] = '\0'; +} + +static void ColouriseGAPDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], Accessor &styler) { + + WordList &keywords1 = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // Do not leak onto next line + if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Prevent SCE_GAP_STRINGEOL from leaking back to previous line + if ( sc.atLineStart ) { + if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING); + if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR); + } + + // Handle line continuation generically + if (sc.ch == '\\' ) { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate + switch (sc.state) { + case SCE_GAP_OPERATOR : + sc.SetState(SCE_GAP_DEFAULT); + break; + + case SCE_GAP_NUMBER : + if (!IsADigit(sc.ch)) { + if (sc.ch == '\\') { + if (!sc.atLineEnd) { + if (!IsADigit(sc.chNext)) { + sc.Forward(); + sc.ChangeState(SCE_GAP_IDENTIFIER); + } + } + } else if (isalpha(sc.ch) || sc.ch == '_') { + sc.ChangeState(SCE_GAP_IDENTIFIER); + } + else sc.SetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_IDENTIFIER : + if (!(iswordstart(static_cast(sc.ch)) || sc.ch == '$')) { + if (sc.ch == '\\') sc.Forward(); + else { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (keywords1.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD4); + } + sc.SetState(SCE_GAP_DEFAULT); + } + } + break; + + case SCE_GAP_COMMENT : + if (sc.atLineEnd) { + sc.SetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_GAP_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_CHAR: + if (sc.atLineEnd) { + sc.ChangeState(SCE_GAP_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_GAP_DEFAULT); + } + break; + } + + // Determine if a new state should be entered + if (sc.state == SCE_GAP_DEFAULT) { + if (IsGAPOperator(static_cast(sc.ch))) { + sc.SetState(SCE_GAP_OPERATOR); + } + else if (IsADigit(sc.ch)) { + sc.SetState(SCE_GAP_NUMBER); + } else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') { + sc.SetState(SCE_GAP_IDENTIFIER); + if (sc.ch == '\\') sc.Forward(); + } else if (sc.ch == '#') { + sc.SetState(SCE_GAP_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_GAP_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_GAP_CHAR); + } + } + + } + sc.Complete(); +} + +static int ClassifyFoldPointGAP(const char* s) { + int level = 0; + if (strcmp(s, "function") == 0 || + strcmp(s, "do") == 0 || + strcmp(s, "if") == 0 || + strcmp(s, "repeat") == 0 ) { + level = 1; + } else if (strcmp(s, "end") == 0 || + strcmp(s, "od") == 0 || + strcmp(s, "fi") == 0 || + strcmp(s, "until") == 0 ) { + level = -1; + } + return level; +} + +static void FoldGAPDoc( Sci_PositionU startPos, Sci_Position length, int initStyle, WordList** , Accessor &styler) { + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + Sci_Position lastStart = 0; + + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) { + // Store last word start point. + lastStart = i; + } + + if (stylePrev == SCE_GAP_KEYWORD) { + if(iswordchar(ch) && !iswordchar(chNext)) { + char s[100]; + GetRange(lastStart, i, styler, s, sizeof(s)); + levelCurrent += ClassifyFoldPointGAP(s); + } + } + + if (atEOL) { + int lev = levelPrev; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const GAPWordListDesc[] = { + "Keywords 1", + "Keywords 2", + "Keywords 3 (unused)", + "Keywords 4 (unused)", + 0 +}; + +extern const LexerModule lmGAP( + SCLEX_GAP, + ColouriseGAPDoc, + "gap", + FoldGAPDoc, + GAPWordListDesc); diff --git a/src/lexilla/lexers/LexGDScript.cxx b/src/lexilla/lexers/LexGDScript.cxx new file mode 100644 index 000000000..4eb6c302c --- /dev/null +++ b/src/lexilla/lexers/LexGDScript.cxx @@ -0,0 +1,772 @@ +// Scintilla source code edit control +/** @file LexGDScript.cxx + ** Lexer for GDScript. + **/ +// Copyright 1998-2002 by Neil Hodgson +// Heavily modified later for GDScript +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "CharacterCategory.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SubStyles.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + +enum kwType { kwOther, kwClass, kwDef, kwExtends}; + +constexpr int indicatorWhitespace = 1; + +bool IsGDStringStart(int ch) { + return (ch == '\'' || ch == '"'); +} + +bool IsGDComment(Accessor &styler, Sci_Position pos, Sci_Position len) { + return len > 0 && styler[pos] == '#'; +} + +constexpr bool IsGDSingleQuoteStringState(int st) noexcept { + return ((st == SCE_GD_CHARACTER) || (st == SCE_GD_STRING)); +} + +constexpr bool IsGDTripleQuoteStringState(int st) noexcept { + return ((st == SCE_GD_TRIPLE) || (st == SCE_GD_TRIPLEDOUBLE)); +} + +char GetGDStringQuoteChar(int st) noexcept { + if ((st == SCE_GD_CHARACTER) || (st == SCE_GD_TRIPLE)) + return '\''; + if ((st == SCE_GD_STRING) || (st == SCE_GD_TRIPLEDOUBLE)) + return '"'; + + return '\0'; +} + +/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */ +int GetGDStringState(Accessor &styler, Sci_Position i, Sci_PositionU *nextIndex) { + char ch = styler.SafeGetCharAt(i); + char chNext = styler.SafeGetCharAt(i + 1); + + if (ch != '"' && ch != '\'') { + *nextIndex = i + 1; + return SCE_GD_DEFAULT; + } + + if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) { + *nextIndex = i + 3; + + if (ch == '"') + return SCE_GD_TRIPLEDOUBLE; + else + return SCE_GD_TRIPLE; + } else { + *nextIndex = i + 1; + + if (ch == '"') + return SCE_GD_STRING; + else + return SCE_GD_CHARACTER; + } +} + +int GetGDStringState(int ch) { + if (ch != '"' && ch != '\'') + return SCE_GD_DEFAULT; + + if (ch == '"') + return SCE_GD_STRING; + else + return SCE_GD_CHARACTER; +} + +inline bool IsAWordChar(int ch, bool unicodeIdentifiers) { + if (IsASCII(ch)) + return (IsAlphaNumeric(ch) || ch == '.' || ch == '_'); + + if (!unicodeIdentifiers) + return false; + + return IsXidContinue(ch); +} + +inline bool IsANodePathChar(int ch, bool unicodeIdentifiers) { + if (IsASCII(ch)) + return (IsAlphaNumeric(ch) || ch == '_' || ch == '/' || ch =='%'); + + if (!unicodeIdentifiers) + return false; + + return IsXidContinue(ch); +} + +inline bool IsAWordStart(int ch, bool unicodeIdentifiers) { + if (IsASCII(ch)) + return (IsUpperOrLowerCase(ch) || ch == '_'); + + if (!unicodeIdentifiers) + return false; + + return IsXidStart(ch); +} + +bool IsFirstNonWhitespace(Sci_Position pos, Accessor &styler) { + const Sci_Position line = styler.GetLine(pos); + const Sci_Position start_pos = styler.LineStart(line); + for (Sci_Position i = start_pos; i < pos; i++) { + const char ch = styler[i]; + if (!(ch == ' ' || ch == '\t')) + return false; + } + return true; +} + +// Options used for LexerGDScript +struct OptionsGDScript { + int whingeLevel; + bool base2or8Literals; + bool stringsOverNewline; + bool keywords2NoSubIdentifiers; + bool fold; + bool foldQuotes; + bool foldCompact; + bool unicodeIdentifiers; + + OptionsGDScript() noexcept { + whingeLevel = 0; + base2or8Literals = true; + stringsOverNewline = false; + keywords2NoSubIdentifiers = false; + fold = false; + foldQuotes = false; + foldCompact = false; + unicodeIdentifiers = true; + } +}; + +const char *const gdscriptWordListDesc[] = { + "Keywords", + "Highlighted identifiers", + nullptr +}; + +struct OptionSetGDScript : public OptionSet { + OptionSetGDScript() { + DefineProperty("lexer.gdscript.whinge.level", &OptionsGDScript::whingeLevel, + "For GDScript code, checks whether indenting is consistent. " + "The default, 0 turns off indentation checking, " + "1 checks whether each line is potentially inconsistent with the previous line, " + "2 checks whether any space characters occur before a tab character in the indentation, " + "3 checks whether any spaces are in the indentation, and " + "4 checks for any tab characters in the indentation. " + "1 is a good level to use."); + + DefineProperty("lexer.gdscript.literals.binary", &OptionsGDScript::base2or8Literals, + "Set to 0 to not recognise binary and octal literals: 0b1011 0o712."); + + DefineProperty("lexer.gdscript.strings.over.newline", &OptionsGDScript::stringsOverNewline, + "Set to 1 to allow strings to span newline characters."); + + DefineProperty("lexer.gdscript.keywords2.no.sub.identifiers", &OptionsGDScript::keywords2NoSubIdentifiers, + "When enabled, it will not style keywords2 items that are used as a sub-identifier. " + "Example: when set, will not highlight \"foo.open\" when \"open\" is a keywords2 item."); + + DefineProperty("fold", &OptionsGDScript::fold); + + DefineProperty("fold.gdscript.quotes", &OptionsGDScript::foldQuotes, + "This option enables folding multi-line quoted strings when using the GDScript lexer."); + + DefineProperty("fold.compact", &OptionsGDScript::foldCompact); + + DefineProperty("lexer.gdscript.unicode.identifiers", &OptionsGDScript::unicodeIdentifiers, + "Set to 0 to not recognise Unicode identifiers."); + + DefineWordListSets(gdscriptWordListDesc); + } +}; + +const char styleSubable[] = { SCE_GD_IDENTIFIER, 0 }; + +LexicalClass lexicalClasses[] = { + // Lexer GDScript SCLEX_GDSCRIPT SCE_GD_: + 0, "SCE_GD_DEFAULT", "default", "White space", + 1, "SCE_GD_COMMENTLINE", "comment line", "Comment", + 2, "SCE_GD_NUMBER", "literal numeric", "Number", + 3, "SCE_GD_STRING", "literal string", "String", + 4, "SCE_GD_CHARACTER", "literal string", "Single quoted string", + 5, "SCE_GD_WORD", "keyword", "Keyword", + 6, "SCE_GD_TRIPLE", "literal string", "Triple quotes", + 7, "SCE_GD_TRIPLEDOUBLE", "literal string", "Triple double quotes", + 8, "SCE_GD_CLASSNAME", "identifier", "Class name definition", + 9, "SCE_GD_FUNCNAME", "identifier", "Function or method name definition", + 10, "SCE_GD_OPERATOR", "operator", "Operators", + 11, "SCE_GD_IDENTIFIER", "identifier", "Identifiers", + 12, "SCE_GD_COMMENTBLOCK", "comment", "Comment-blocks", + 13, "SCE_GD_STRINGEOL", "error literal string", "End of line where string is not closed", + 14, "SCE_GD_WORD2", "identifier", "Highlighted identifiers", + 15, "SCE_GD_ANNOTATION", "annotation", "Annotations", + 16, "SCE_GD_NODEPATH", "path", "Node path", +}; + +} + +class LexerGDScript : public DefaultLexer { + WordList keywords; + WordList keywords2; + OptionsGDScript options; + OptionSetGDScript osGDScript; + enum { ssIdentifier }; + SubStyles subStyles{styleSubable}; +public: + explicit LexerGDScript() : + DefaultLexer("gdscript", SCLEX_GDSCRIPT, lexicalClasses, ELEMENTS(lexicalClasses)) { + } + ~LexerGDScript() override { + } + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char *SCI_METHOD PropertyNames() override { + return osGDScript.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osGDScript.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) override { + return osGDScript.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char *key) override { + return osGDScript.PropertyGet(key); + } + const char *SCI_METHOD DescribeWordListSets() override { + return osGDScript.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void *SCI_METHOD PrivateCall(int, void *) override { + return nullptr; + } + + int SCI_METHOD LineEndTypesSupported() override { + return SC_LINE_END_TYPE_UNICODE; + } + + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) override { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) override { + return subStyles.Length(styleBase); + } + int SCI_METHOD StyleFromSubStyle(int subStyle) override { + const int styleBase = subStyles.BaseStyle(subStyle); + return styleBase; + } + int SCI_METHOD PrimaryStyleFromStyle(int style) override { + return style; + } + void SCI_METHOD FreeSubStyles() override { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override { + subStyles.SetIdentifiers(style, identifiers); + } + int SCI_METHOD DistanceToSecondaryStyles() override { + return 0; + } + const char *SCI_METHOD GetSubStyleBases() override { + return styleSubable; + } + + static ILexer5 *LexerFactoryGDScript() { + return new LexerGDScript(); + } + +private: + void ProcessLineEnd(StyleContext &sc, bool &inContinuedString); +}; + +Sci_Position SCI_METHOD LexerGDScript::PropertySet(const char *key, const char *val) { + if (osGDScript.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerGDScript::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + default: + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void LexerGDScript::ProcessLineEnd(StyleContext &sc, bool &inContinuedString) { + if ((sc.state == SCE_GD_DEFAULT) + || IsGDTripleQuoteStringState(sc.state)) { + // Perform colourisation of white space and triple quoted strings at end of each line to allow + // tab marking to work inside white space and triple quoted strings + sc.SetState(sc.state); + } + + if (IsGDSingleQuoteStringState(sc.state)) { + if (inContinuedString || options.stringsOverNewline) { + inContinuedString = false; + } else { + sc.ChangeState(SCE_GD_STRINGEOL); + sc.ForwardSetState(SCE_GD_DEFAULT); + } + } +} + +void SCI_METHOD LexerGDScript::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + Accessor styler(pAccess, nullptr); + + const Sci_Position endPos = startPos + length; + + // Backtrack to previous line in case need to fix its tab whinging + Sci_Position lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + // Look for backslash-continued lines + while (lineCurrent > 0) { + const Sci_Position eolPos = styler.LineStart(lineCurrent) - 1; + const int eolStyle = styler.StyleAt(eolPos); + if (eolStyle == SCE_GD_STRING || eolStyle == SCE_GD_CHARACTER + || eolStyle == SCE_GD_STRINGEOL) { + lineCurrent -= 1; + } else { + break; + } + } + startPos = styler.LineStart(lineCurrent); + } + initStyle = startPos == 0 ? SCE_GD_DEFAULT : styler.StyleAt(startPos - 1); + } + + initStyle = initStyle & 31; + if (initStyle == SCE_GD_STRINGEOL) { + initStyle = SCE_GD_DEFAULT; + } + + kwType kwLast = kwOther; + int spaceFlags = 0; + styler.IndentAmount(lineCurrent, &spaceFlags, IsGDComment); + bool base_n_number = false; + + const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_GD_IDENTIFIER); + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + bool indentGood = true; + Sci_Position startIndicator = sc.currentPos; + bool inContinuedString = false; + bool percentIsNodePath = false; + int nodePathStringState = SCE_GD_DEFAULT; + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + styler.IndentAmount(lineCurrent, &spaceFlags, IsGDComment); + indentGood = true; + if (options.whingeLevel == 1) { + indentGood = (spaceFlags & wsInconsistent) == 0; + } else if (options.whingeLevel == 2) { + indentGood = (spaceFlags & wsSpaceTab) == 0; + } else if (options.whingeLevel == 3) { + indentGood = (spaceFlags & wsSpace) == 0; + } else if (options.whingeLevel == 4) { + indentGood = (spaceFlags & wsTab) == 0; + } + if (!indentGood) { + styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); + startIndicator = sc.currentPos; + } + } + + if (sc.atLineEnd) { + percentIsNodePath = false; + ProcessLineEnd(sc, inContinuedString); + lineCurrent++; + if (!sc.More()) + break; + } + + bool needEOLCheck = false; + + if (sc.state == SCE_GD_OPERATOR) { + kwLast = kwOther; + sc.SetState(SCE_GD_DEFAULT); + } else if (sc.state == SCE_GD_NUMBER) { + if (!IsAWordChar(sc.ch, false) && + !(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_GD_DEFAULT); + } + } else if (sc.state == SCE_GD_IDENTIFIER) { + if ((sc.ch == '.') || (!IsAWordChar(sc.ch, options.unicodeIdentifiers))) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + int style = SCE_GD_IDENTIFIER; + if (keywords.InList(s)) { + style = SCE_GD_WORD; + } else if (kwLast == kwClass) { + style = SCE_GD_CLASSNAME; + } else if (kwLast == kwDef) { + style = SCE_GD_FUNCNAME; + } else if (keywords2.InList(s)) { + if (options.keywords2NoSubIdentifiers) { + // We don't want to highlight keywords2 + // that are used as a sub-identifier, + // i.e. not open in "foo.open". + const Sci_Position pos = styler.GetStartSegment() - 1; + if (pos < 0 || (styler.SafeGetCharAt(pos, '\0') != '.')) + style = SCE_GD_WORD2; + } else { + style = SCE_GD_WORD2; + } + } else { + const int subStyle = classifierIdentifiers.ValueFor(s); + if (subStyle >= 0) { + style = subStyle; + } + } + sc.ChangeState(style); + sc.SetState(SCE_GD_DEFAULT); + if (style == SCE_GD_WORD) { + if (0 == strcmp(s, "class")) + kwLast = kwClass; + else if (0 == strcmp(s, "func")) + kwLast = kwDef; + else if (0 == strcmp(s, "extends")) + kwLast = kwExtends; + else + kwLast = kwOther; + } else { + kwLast = kwOther; + } + } + } else if ((sc.state == SCE_GD_COMMENTLINE) || (sc.state == SCE_GD_COMMENTBLOCK)) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_GD_DEFAULT); + } + } else if (sc.state == SCE_GD_ANNOTATION) { + if (!IsAWordStart(sc.ch, options.unicodeIdentifiers)) { + sc.SetState(SCE_GD_DEFAULT); + } + } else if (sc.state == SCE_GD_NODEPATH) { + if (nodePathStringState != SCE_GD_DEFAULT) { + if (sc.ch == GetGDStringQuoteChar(nodePathStringState) ) { + nodePathStringState = SCE_GD_DEFAULT; + } + } else { + if (IsGDStringStart(sc.ch)) { + nodePathStringState = GetGDStringState(sc.ch); + } else if (!IsANodePathChar(sc.ch, options.unicodeIdentifiers)) { + sc.SetState(SCE_GD_DEFAULT); + } + } + } else if (IsGDSingleQuoteStringState(sc.state)) { + if (sc.ch == '\\') { + if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) { + sc.Forward(); + } + if (sc.chNext == '\n' || sc.chNext == '\r') { + inContinuedString = true; + } else { + // Don't roll over the newline. + sc.Forward(); + } + } else if (sc.ch == GetGDStringQuoteChar(sc.state)) { + sc.ForwardSetState(SCE_GD_DEFAULT); + needEOLCheck = true; + } + } else if (sc.state == SCE_GD_TRIPLE) { + if (sc.ch == '\\') { + sc.Forward(); + } else if (sc.Match(R"(''')")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_GD_DEFAULT); + needEOLCheck = true; + } + } else if (sc.state == SCE_GD_TRIPLEDOUBLE) { + if (sc.ch == '\\') { + sc.Forward(); + } else if (sc.Match(R"(""")")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_GD_DEFAULT); + needEOLCheck = true; + } + } + + if (!indentGood && !IsASpaceOrTab(sc.ch)) { + styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 1); + startIndicator = sc.currentPos; + indentGood = true; + } + + // State exit code may have moved on to end of line + if (needEOLCheck && sc.atLineEnd) { + ProcessLineEnd(sc, inContinuedString); + lineCurrent++; + styler.IndentAmount(lineCurrent, &spaceFlags, IsGDComment); + if (!sc.More()) + break; + } + + // Check for a new state starting character + if (sc.state == SCE_GD_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) { + base_n_number = true; + sc.SetState(SCE_GD_NUMBER); + } else if (sc.ch == '0' && + (sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) { + if (options.base2or8Literals) { + base_n_number = true; + sc.SetState(SCE_GD_NUMBER); + } else { + sc.SetState(SCE_GD_NUMBER); + sc.ForwardSetState(SCE_GD_IDENTIFIER); + } + } else { + base_n_number = false; + sc.SetState(SCE_GD_NUMBER); + } + } else if ((sc.ch == '$') || (sc.ch == '%' && (percentIsNodePath || IsFirstNonWhitespace(sc.currentPos, styler)))) { + percentIsNodePath = false; + sc.SetState(SCE_GD_NODEPATH); + } else if (isoperator(sc.ch) || sc.ch == '`') { + percentIsNodePath = !((sc.ch == ')') || (sc.ch == ']') || (sc.ch == '}')); + sc.SetState(SCE_GD_OPERATOR); + } else if (sc.ch == '#') { + sc.SetState(sc.chNext == '#' ? SCE_GD_COMMENTBLOCK : SCE_GD_COMMENTLINE); + } else if (sc.ch == '@') { + if (IsFirstNonWhitespace(sc.currentPos, styler)) + sc.SetState(SCE_GD_ANNOTATION); + else + sc.SetState(SCE_GD_OPERATOR); + } else if (IsGDStringStart(sc.ch)) { + Sci_PositionU nextIndex = 0; + sc.SetState(GetGDStringState(styler, sc.currentPos, &nextIndex)); + while (nextIndex > (sc.currentPos + 1) && sc.More()) { + sc.Forward(); + } + } else if (IsAWordStart(sc.ch, options.unicodeIdentifiers)) { + sc.SetState(SCE_GD_IDENTIFIER); + } + } + } + styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); + sc.Complete(); +} + +static bool IsCommentLine(Sci_Position line, Accessor &styler) { + const Sci_Position pos = styler.LineStart(line); + const Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + for (Sci_Position i = pos; i < eol_pos; i++) { + const char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static bool IsQuoteLine(Sci_Position line, const Accessor &styler) { + const int style = styler.StyleAt(styler.LineStart(line)) & 31; + return IsGDTripleQuoteStringState(style); +} + + +void SCI_METHOD LexerGDScript::Fold(Sci_PositionU startPos, Sci_Position length, int /*initStyle - unused*/, IDocument *pAccess) { + if (!options.fold) + return; + + Accessor styler(pAccess, nullptr); + + const Sci_Position maxPos = startPos + length; + const Sci_Position maxLines = (maxPos == styler.Length()) ? styler.GetLine(maxPos) : styler.GetLine(maxPos - 1); // Requested last line + const Sci_Position docLines = styler.GetLine(styler.Length()); // Available last line + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines (needed esp. within triple quoted strings) + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + int spaceFlags = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, nullptr); + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, nullptr); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && + (!IsCommentLine(lineCurrent, styler)) && + (!IsQuoteLine(lineCurrent, styler))) + break; + } + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + // Set up initial loop state + startPos = styler.LineStart(lineCurrent); + int prev_state = SCE_GD_DEFAULT & 31; + if (lineCurrent >= 1) + prev_state = styler.StyleAt(startPos - 1) & 31; + int prevQuote = options.foldQuotes && IsGDTripleQuoteStringState(prev_state); + + // Process all characters to end of requested range or end of any triple quote + //that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of unclosed quote at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote)) { + + // Gather info + int lev = indentCurrent; + Sci_Position lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + int quote = false; + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + indentNext = styler.IndentAmount(lineNext, &spaceFlags, nullptr); + const Sci_Position lookAtPos = (styler.LineStart(lineNext) == styler.Length()) ? styler.Length() - 1 : styler.LineStart(lineNext); + const int style = styler.StyleAt(lookAtPos) & 31; + quote = options.foldQuotes && IsGDTripleQuoteStringState(style); + } + const bool quote_start = (quote && !prevQuote); + const bool quote_continue = (quote && prevQuote); + if (!quote || !prevQuote) + indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + if (quote) + indentNext = indentCurrentLevel; + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + if (quote_start) { + // Place fold point at start of triple quoted string + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (quote_continue || prevQuote) { + // Add level to rest of lines in the string + lev = lev + 1; + } + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. If comments end file, use the min + // comment indent as the level after + + int minCommentLevel = indentCurrentLevel; + while (!quote && + (lineNext < docLines) && + ((indentNext & SC_FOLDLEVELWHITEFLAG) || (IsCommentLine(lineNext, styler)))) { + + if (IsCommentLine(lineNext, styler) && indentNext < minCommentLevel) { + minCommentLevel = indentNext; + } + + lineNext++; + indentNext = styler.IndentAmount(lineNext, &spaceFlags, nullptr); + } + + const int levelAfterComments = ((lineNext < docLines) ? indentNext & SC_FOLDLEVELNUMBERMASK : minCommentLevel); + const int levelBeforeComments = std::max(indentCurrentLevel, levelAfterComments); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + Sci_Position skipLine = lineNext; + int skipLevel = levelAfterComments; + + while (--skipLine > lineCurrent) { + const int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, nullptr); + + if (options.foldCompact) { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) + skipLevel = levelBeforeComments; + + const int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } else { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && + !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && + !IsCommentLine(skipLine, styler)) + skipLevel = levelBeforeComments; + + styler.SetLevel(skipLine, skipLevel); + } + } + + // Set fold header on non-quote line + if (!quote && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Keep track of triple quote state of previous line + prevQuote = quote; + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, options.foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG); + indentCurrent = indentNext; + lineCurrent = lineNext; + } + + // NOTE: Cannot set level of last line here because indentCurrent doesn't have + // header flag set; the loop above is crafted to take care of this case! + //styler.SetLevel(lineCurrent, indentCurrent); +} + +extern const LexerModule lmGDScript(SCLEX_GDSCRIPT, LexerGDScript::LexerFactoryGDScript, "gdscript", + gdscriptWordListDesc); diff --git a/src/lexilla/lexers/LexGui4Cli.cxx b/src/lexilla/lexers/LexGui4Cli.cxx new file mode 100644 index 000000000..d7fc0c486 --- /dev/null +++ b/src/lexilla/lexers/LexGui4Cli.cxx @@ -0,0 +1,315 @@ +// Scintilla source code edit control +// Copyright 1998-2002 by Neil Hodgson +// @file LexGui4Cli.cxx +/* +This is the Lexer for Gui4Cli, included in SciLexer.dll +- by d. Keletsekis, 2/10/2003 + +To add to SciLexer.dll: +1. Add the values below to INCLUDE\Scintilla.iface +2. Run the scripts/HFacer.py script +3. Run the scripts/LexGen.py script + +val SCE_GC_DEFAULT=0 +val SCE_GC_COMMENTLINE=1 +val SCE_GC_COMMENTBLOCK=2 +val SCE_GC_GLOBAL=3 +val SCE_GC_EVENT=4 +val SCE_GC_ATTRIBUTE=5 +val SCE_GC_CONTROL=6 +val SCE_GC_COMMAND=7 +val SCE_GC_STRING=8 +val SCE_GC_OPERATOR=9 +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +#define debug Platform::DebugPrintf + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\'); +} + +inline bool isGCOperator(int ch) +{ if (isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '%' || + ch == '[' || ch == ']' || ch == '<' || ch == '>' || + ch == ',' || ch == ';' || ch == ':') + return true; + return false; +} + +#define isSpace(x) ((x)==' ' || (x)=='\t') +#define isNL(x) ((x)=='\n' || (x)=='\r') +#define isSpaceOrNL(x) (isSpace(x) || isNL(x)) +#define BUFFSIZE 500 +#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024) + +static void colorFirstWord(WordList *keywordlists[], Accessor &styler, + StyleContext *sc, char *buff, Sci_Position length, Sci_Position) +{ + Sci_Position c = 0; + while (sc->More() && isSpaceOrNL(sc->ch)) + { sc->Forward(); + } + styler.ColourTo(sc->currentPos - 1, sc->state); + + if (!IsAWordChar(sc->ch)) // comment, marker, etc.. + return; + + while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch)) + { buff[c] = static_cast(sc->ch); + ++c; sc->Forward(); + } + buff[c] = '\0'; + char *p = buff; + while (*p) // capitalize.. + { if (islower(*p)) *p = static_cast(toupper(*p)); + ++p; + } + + WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user + WordList &kEvent = *keywordlists[1]; + WordList &kAttribute = *keywordlists[2]; + WordList &kControl = *keywordlists[3]; + WordList &kCommand = *keywordlists[4]; + + int state = 0; + // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; + // debug ("line = %d, level = %d", line, level); + + if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL; + else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE; + else if (kControl.InList(buff)) state = SCE_GC_CONTROL; + else if (kCommand.InList(buff)) state = SCE_GC_COMMAND; + else if (kEvent.InList(buff)) state = SCE_GC_EVENT; + + if (state) + { sc->ChangeState(state); + styler.ColourTo(sc->currentPos - 1, sc->state); + sc->ChangeState(SCE_GC_DEFAULT); + } + else + { sc->ChangeState(SCE_GC_DEFAULT); + styler.ColourTo(sc->currentPos - 1, sc->state); + } +} + +// Main colorizing function called by Scintilla +static void +ColouriseGui4CliDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + styler.StartAt(startPos); + + Sci_Position currentline = styler.GetLine(startPos); + int quotestart = 0, oldstate; + styler.StartSegment(startPos); + bool noforward; + char buff[BUFFSIZE+1]; // buffer for command name + + StyleContext sc(startPos, length, initStyle, styler); + buff[0] = '\0'; // cbuff = 0; + + if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word.. + colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + + while (sc.More()) + { noforward = 0; + + switch (sc.ch) + { + case '/': + if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING) + break; + if (sc.chNext == '/') // line comment + { sc.SetState (SCE_GC_COMMENTLINE); + sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + } + else if (sc.chNext == '*') // block comment + { sc.SetState(SCE_GC_COMMENTBLOCK); + sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + } + else + styler.ColourTo(sc.currentPos, sc.state); + break; + + case '*': // end of comment block, or operator.. + if (sc.state == SCE_GC_STRING) + break; + if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/') + { sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState (SCE_GC_DEFAULT); + } + else + styler.ColourTo(sc.currentPos, sc.state); + break; + + case '\'': case '\"': // strings.. + if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE) + break; + if (sc.state == SCE_GC_STRING) + { if (sc.ch == quotestart) // match same quote char.. + { styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState(SCE_GC_DEFAULT); + quotestart = 0; + } } + else + { styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_GC_STRING); + quotestart = sc.ch; + } + break; + + case ';': // end of commandline character + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && + sc.state != SCE_GC_STRING) + { + styler.ColourTo(sc.currentPos - 1, sc.state); + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(SCE_GC_DEFAULT); + sc.Forward(); + colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + noforward = 1; // don't move forward - already positioned at next char.. + } + break; + + case '+': case '-': case '=': case '!': // operators.. + case '<': case '>': case '&': case '|': case '$': + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && + sc.state != SCE_GC_STRING) + { + styler.ColourTo(sc.currentPos - 1, sc.state); + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(SCE_GC_DEFAULT); + } + break; + + case '\\': // escape - same as operator, but also mark in strings.. + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE) + { + oldstate = sc.state; + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); // mark also the next char.. + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(oldstate); + } + break; + + case '\n': case '\r': + ++currentline; + if (sc.state == SCE_GC_COMMENTLINE) + { styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState (SCE_GC_DEFAULT); + } + else if (sc.state != SCE_GC_COMMENTBLOCK) + { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + noforward = 1; // don't move forward - already positioned at next char.. + } + break; + +// case ' ': case '\t': +// default : + } + + if (!noforward) sc.Forward(); + + } + sc.Complete(); +} + +// Main folding function called by Scintilla - (based on props (.ini) files function) +static void FoldGui4Cli(Sci_PositionU startPos, Sci_Position length, int, + WordList *[], Accessor &styler) +{ + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + bool headerPoint = false; + + for (Sci_PositionU i = startPos; i < endPos; i++) + { + char ch = chNext; + chNext = styler[i+1]; + + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL) + { headerPoint = true; // fold at events and globals + } + + if (atEOL) + { int lev = SC_FOLDLEVELBASE+1; + + if (headerPoint) + lev = SC_FOLDLEVELBASE; + + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + + if (headerPoint) + lev |= SC_FOLDLEVELHEADERFLAG; + + if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct + { styler.SetLevel(lineCurrent, lev); + } + + lineCurrent++; // re-initialize our flags + visibleChars = 0; + headerPoint = false; + } + + if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK))) + visibleChars++; + } + + int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1; + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, lev | flagsNext); +} + +// I have no idea what these are for.. probably accessible by some message. +static const char * const gui4cliWordListDesc[] = { + "Globals", "Events", "Attributes", "Control", "Commands", + 0 +}; + +// Declare language & pass our function pointers to Scintilla +extern const LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc); + +#undef debug + diff --git a/src/lexilla/lexers/LexHTML.cxx b/src/lexilla/lexers/LexHTML.cxx new file mode 100644 index 000000000..53272817a --- /dev/null +++ b/src/lexilla/lexers/LexHTML.cxx @@ -0,0 +1,2763 @@ +// Scintilla source code edit control +/** @file LexHTML.cxx + ** Lexer for HTML. + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "InList.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SubStyles.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + +#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START) +#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START) +#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START) + +enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment }; +enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; + +constexpr bool IsAWordChar(int ch) noexcept { + return IsAlphaNumeric(ch) || ch == '.' || ch == '_'; +} + +constexpr bool IsAWordStart(int ch) noexcept { + return IsAlphaNumeric(ch) || ch == '_'; +} + +bool IsOperator(int ch) noexcept { + if (IsAlphaNumeric(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || + ch == '(' || ch == ')' || ch == '-' || ch == '+' || + ch == '=' || ch == '|' || ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ':' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || ch == '/' || + ch == '?' || ch == '!' || ch == '.' || ch == '~') + return true; + return false; +} + +unsigned char SafeGetUnsignedCharAt(Accessor &styler, Sci_Position position, char chDefault = ' ') { + return styler.SafeGetCharAt(position, chDefault); +} + +// Put an upper limit to bound time taken for unexpected text. +constexpr Sci_PositionU maxLengthCheck = 200; + +std::string GetNextWord(Accessor &styler, Sci_PositionU start) { + std::string ret; + for (Sci_PositionU i = 0; i < maxLengthCheck; i++) { + const char ch = styler.SafeGetCharAt(start + i); + if ((i == 0) && !IsAWordStart(ch)) + break; + if ((i > 0) && !IsAWordChar(ch)) + break; + ret.push_back(ch); + } + return ret; +} + +bool Contains(const std::string &s, std::string_view search) noexcept { + return s.find(search) != std::string::npos; +} + +script_type segIsScriptingIndicator(Accessor &styler, Sci_PositionU start, Sci_PositionU end, script_type prevValue) { + const std::string s = styler.GetRangeLowered(start, end+1); + if (Contains(s, "vbs")) + return eScriptVBS; + if (Contains(s, "pyth")) + return eScriptPython; + // https://html.spec.whatwg.org/multipage/scripting.html#attr-script-type + // https://mimesniff.spec.whatwg.org/#javascript-mime-type + if (Contains(s, "javas") || Contains(s, "ecmas") || Contains(s, "module") || Contains(s, "jscr")) + return eScriptJS; + if (Contains(s, "php")) + return eScriptPHP; + if (Contains(s, "xml")) { + const size_t xml = s.find("xml"); + if (xml != std::string::npos) { + for (size_t t = 0; t < xml; t++) { + if (!IsASpace(s[t])) { + return prevValue; + } + } + } + return eScriptXML; + } + + return prevValue; +} + +int PrintScriptingIndicatorOffset(Accessor &styler, Sci_PositionU start, Sci_PositionU end) { + int iResult = 0; + const std::string s = styler.GetRangeLowered(start, end+1); + if (0 == strncmp(s.c_str(), "php", 3)) { + iResult = 3; + } + return iResult; +} + +script_type ScriptOfState(int state) noexcept { + if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + return eScriptPython; + } else if ((state >= SCE_HB_START && state <= SCE_HB_STRINGEOL) || (state == SCE_H_ASPAT || state == SCE_H_XCCOMMENT)) { + return eScriptVBS; + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + return eScriptJS; + } else if ((state >= SCE_HPHP_DEFAULT && state <= SCE_HPHP_COMMENTLINE) || (state == SCE_HPHP_COMPLEX_VARIABLE)) { + return eScriptPHP; + } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) { + return eScriptSGML; + } else if (state == SCE_H_SGML_BLOCK_DEFAULT) { + return eScriptSGMLblock; + } else { + return eScriptNone; + } +} + +constexpr int statePrintForState(int state, script_mode inScriptType) noexcept { + int StateToPrint = state; + + if (state >= SCE_HJ_START) { + if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON); + } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS); + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS); + } + } + + return StateToPrint; +} + +constexpr int stateForPrintState(int StateToPrint) noexcept { + int state = StateToPrint; + + if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) { + state = StateToPrint - SCE_HA_PYTHON; + } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) { + state = StateToPrint - SCE_HA_VBS; + } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) { + state = StateToPrint - SCE_HA_JS; + } + + return state; +} + +constexpr bool IsNumberChar(char ch) noexcept { + return IsADigit(ch) || ch == '.' || ch == '-' || ch == '#'; +} + +constexpr bool isStringState(int state) noexcept { + bool bResult = false; + + switch (state) { + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJA_DOUBLESTRING: + case SCE_HJA_SINGLESTRING: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_CHARACTER: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPA_STRING: + case SCE_HPA_CHARACTER: + case SCE_HPA_TRIPLE: + case SCE_HPA_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_HSTRING_VARIABLE: + case SCE_HPHP_COMPLEX_VARIABLE: + bResult = true; + break; + default : + break; + } + return bResult; +} + +constexpr bool stateAllowsTermination(int state) noexcept { + bool allowTermination = !isStringState(state); + if (allowTermination) { + switch (state) { + case SCE_HPHP_COMMENT: + case SCE_HP_COMMENTLINE: + case SCE_HPA_COMMENTLINE: + allowTermination = false; + break; + default: + break; + } + } + return allowTermination; +} + +bool isPreProcessorEndTag(int state, int ch) noexcept { + const script_type type = ScriptOfState(state); + if (state == SCE_H_ASP || AnyOf(type, eScriptVBS, eScriptJS, eScriptPython)) { + return ch == '%'; + } + if (type == eScriptPHP) { + return ch == '%' || ch == '?'; + } + return ch == '?'; +} + +// not really well done, since it's only comments that should lex the %> and <% +constexpr bool isCommentASPState(int state) noexcept { + bool bResult = false; + + switch (state) { + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTLINE: + case SCE_HJ_COMMENTDOC: + case SCE_HB_COMMENTLINE: + case SCE_HP_COMMENTLINE: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + bResult = true; + break; + default : + break; + } + return bResult; +} + +bool classifyAttribHTML(script_mode inScriptType, Sci_PositionU start, Sci_PositionU end, const WordList &keywords, const WordClassifier &classifier, Accessor &styler, const std::string &tag) { + int chAttr = SCE_H_ATTRIBUTEUNKNOWN; + bool isLanguageType = false; + if (IsNumberChar(styler[start])) { + chAttr = SCE_H_NUMBER; + } else { + const std::string s = styler.GetRangeLowered(start, end+1); + if (keywords.InList(s)) { + chAttr = SCE_H_ATTRIBUTE; + } else { + int subStyle = classifier.ValueFor(s); + if (subStyle < 0) { + // Didn't find attribute, check for tag.attribute + const std::string tagAttribute = tag + "." + s; + subStyle = classifier.ValueFor(tagAttribute); + } + if (subStyle >= 0) { + chAttr = subStyle; + } + } + + if (inScriptType == eNonHtmlScript) { + // see https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model + if (s == "type" || s == "language") { + isLanguageType = true; + } + } + } + if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords) + // No keywords -> all are known + chAttr = SCE_H_ATTRIBUTE; + styler.ColourTo(end, chAttr); + return isLanguageType; +} + +// https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-core-concepts +bool isHTMLCustomElement(const std::string &tag) noexcept { + // check valid HTML custom element name: starts with an ASCII lower alpha and contains hyphen. + // IsUpperOrLowerCase() is used for `html.tags.case.sensitive=1`. + if (tag.length() < 2 || !IsUpperOrLowerCase(tag[0])) { + return false; + } + if (tag.find('-') == std::string::npos) { + return false; + } + return true; +} + +int classifyTagHTML(Sci_PositionU start, Sci_PositionU end, + const WordList &keywords, const WordClassifier &classifier, Accessor &styler, bool &tagDontFold, + bool caseSensitive, bool isXml, bool allowScripts, + const std::set &nonFoldingTags, + std::string &tag) { + tag.clear(); + // Copy after the '<' and stop before ' ' + for (Sci_PositionU cPos = start; cPos <= end; cPos++) { + const char ch = styler[cPos]; + if (IsASpace(ch)) { + break; + } + if ((ch != '<') && (ch != '/')) { + tag.push_back(caseSensitive ? ch : MakeLowerCase(ch)); + } + } + // if the current language is XML, I can fold any tag + // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.) + //...to find it in the list of no-container-tags + tagDontFold = (!isXml) && (nonFoldingTags.count(tag) > 0); + // No keywords -> all are known + int chAttr = SCE_H_TAGUNKNOWN; + if (!tag.empty() && (tag[0] == '!')) { + chAttr = SCE_H_SGML_DEFAULT; + } else if (!keywords || keywords.InList(tag)) { + chAttr = SCE_H_TAG; + } else if (!isXml && isHTMLCustomElement(tag)) { + chAttr = SCE_H_TAG; + } else { + const int subStyle = classifier.ValueFor(tag); + if (subStyle >= 0) { + chAttr = subStyle; + } + } + if (chAttr != SCE_H_TAGUNKNOWN) { + styler.ColourTo(end, chAttr); + } + if (chAttr == SCE_H_TAG) { + if (allowScripts && (tag == "script")) { + // check to see if this is a self-closing tag by sniffing ahead + bool isSelfClose = false; + for (Sci_PositionU cPos = end; cPos <= end + maxLengthCheck; cPos++) { + const char ch = styler.SafeGetCharAt(cPos, '\0'); + if (ch == '\0' || ch == '>') + break; + if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') { + isSelfClose = true; + break; + } + } + + // do not enter a script state if the tag self-closed + if (!isSelfClose) + chAttr = SCE_H_SCRIPT; + } else if (!isXml && (tag == "comment")) { + chAttr = SCE_H_COMMENT; + } + } + return chAttr; +} + +void classifyWordHTJS(Sci_PositionU start, Sci_PositionU end, + const WordList &keywords, const WordClassifier &classifier, const WordClassifier &classifierServer, Accessor &styler, script_mode inScriptType) { + const std::string s = styler.GetRange(start, end+1); + int chAttr = SCE_HJ_WORD; + const bool wordIsNumber = IsADigit(s[0]) || ((s[0] == '.') && IsADigit(s[1])); + if (wordIsNumber) { + chAttr = SCE_HJ_NUMBER; + } else if (keywords.InList(s)) { + chAttr = SCE_HJ_KEYWORD; + } else { + const int subStyle = (inScriptType == eNonHtmlScript) ? classifier.ValueFor(s) : classifierServer.ValueFor(s); + if (subStyle >= 0) { + chAttr = subStyle; + } + } + + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); +} + +int classifyWordHTVB(Sci_PositionU start, Sci_PositionU end, const WordList &keywords, const WordClassifier &classifier, Accessor &styler, script_mode inScriptType) { + int chAttr = SCE_HB_IDENTIFIER; + const bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); + if (wordIsNumber) { + chAttr = SCE_HB_NUMBER; + } else { + const std::string s = styler.GetRangeLowered(start, end+1); + if (keywords.InList(s)) { + chAttr = SCE_HB_WORD; + if (s == "rem") + chAttr = SCE_HB_COMMENTLINE; + } else { + const int subStyle = classifier.ValueFor(s); + if (subStyle >= 0) { + chAttr = subStyle; + } + } + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + if (chAttr == SCE_HB_COMMENTLINE) + return SCE_HB_COMMENTLINE; + else + return SCE_HB_DEFAULT; +} + +void classifyWordHTPy(Sci_PositionU start, Sci_PositionU end, const WordList &keywords, const WordClassifier &classifier, Accessor &styler, std::string &prevWord, script_mode inScriptType, bool isMako) { + const bool wordIsNumber = IsADigit(styler[start]); + const std::string s = styler.GetRange(start, end + 1); + int chAttr = SCE_HP_IDENTIFIER; + if (prevWord == "class") + chAttr = SCE_HP_CLASSNAME; + else if (prevWord == "def") + chAttr = SCE_HP_DEFNAME; + else if (wordIsNumber) + chAttr = SCE_HP_NUMBER; + else if (keywords.InList(s)) + chAttr = SCE_HP_WORD; + else if (isMako && (s == "block")) + chAttr = SCE_HP_WORD; + else { + const int subStyle = classifier.ValueFor(s); + if (subStyle >= 0) { + chAttr = subStyle; + } + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + prevWord = s; +} + +// Update the word colour to default or keyword +// Called when in a PHP word +void classifyWordHTPHP(Sci_PositionU start, Sci_PositionU end, const WordList &keywords, const WordClassifier &classifier, Accessor &styler) { + int chAttr = SCE_HPHP_DEFAULT; + const bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1])); + if (wordIsNumber) { + chAttr = SCE_HPHP_NUMBER; + } else { + const std::string s = styler.GetRangeLowered(start, end+1);; + if (keywords.InList(s)) { + chAttr = SCE_HPHP_WORD; + } else { + const int subStyle = classifier.ValueFor(s); + if (subStyle >= 0) { + chAttr = subStyle; + } + } + } + styler.ColourTo(end, chAttr); +} + +bool isWordHSGML(Sci_PositionU start, Sci_PositionU end, const WordList &keywords, Accessor &styler) { + const std::string s = styler.GetRange(start, end + 1); + return keywords.InList(s); +} + +bool isWordCdata(Sci_PositionU start, Sci_PositionU end, Accessor &styler) { + const std::string s = styler.GetRange(start, end + 1); + return s == "[CDATA["; +} + +// Return the first state to reach when entering a scripting language +constexpr int StateForScript(script_type scriptLanguage) noexcept { + int Result = SCE_HJ_START; + switch (scriptLanguage) { + case eScriptVBS: + Result = SCE_HB_START; + break; + case eScriptPython: + Result = SCE_HP_START; + break; + case eScriptPHP: + Result = SCE_HPHP_DEFAULT; + break; + case eScriptXML: + Result = SCE_H_TAGUNKNOWN; + break; + case eScriptSGML: + Result = SCE_H_SGML_DEFAULT; + break; + case eScriptComment: + Result = SCE_H_COMMENT; + break; + default : + break; + } + return Result; +} + +constexpr bool issgmlwordchar(int ch) noexcept { + return !IsASCII(ch) || + (IsAlphaNumeric(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '['); +} + +constexpr bool IsPhpWordStart(int ch) noexcept { + return (IsUpperOrLowerCase(ch) || (ch == '_')) || (ch >= 0x7f); +} + +constexpr bool IsPhpWordChar(int ch) noexcept { + return IsADigit(ch) || IsPhpWordStart(ch); +} + +constexpr bool InTagState(int state) noexcept { + return AnyOf(state, SCE_H_TAG, SCE_H_TAGUNKNOWN, SCE_H_SCRIPT, + SCE_H_ATTRIBUTE, SCE_H_ATTRIBUTEUNKNOWN, + SCE_H_NUMBER, SCE_H_OTHER, + SCE_H_DOUBLESTRING, SCE_H_SINGLESTRING); +} + +constexpr bool IsCommentState(const int state) noexcept { + return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT; +} + +constexpr bool IsScriptCommentState(const int state) noexcept { + return AnyOf(state, SCE_HJ_COMMENT, SCE_HJ_COMMENTLINE, SCE_HJA_COMMENT, + SCE_HJA_COMMENTLINE, SCE_HB_COMMENTLINE, SCE_HBA_COMMENTLINE); +} + +constexpr bool isLineEnd(int ch) noexcept { + return ch == '\r' || ch == '\n'; +} + +bool isMakoBlockEnd(const int ch, const int chNext, const std::string &blockType) noexcept { + if (blockType.empty()) { + return ((ch == '%') && (chNext == '>')); + } else if (InList(blockType, { "inherit", "namespace", "include", "page" })) { + return ((ch == '/') && (chNext == '>')); + } else if (blockType == "%") { + if (ch == '/' && isLineEnd(chNext)) + return true; + else + return isLineEnd(ch); + } else if (blockType == "{") { + return ch == '}'; + } else { + return (ch == '>'); + } +} + +bool isDjangoBlockEnd(const int ch, const int chNext, const std::string &blockType) noexcept { + if (blockType.empty()) { + return false; + } else if (blockType == "%") { + return ((ch == '%') && (chNext == '}')); + } else if (blockType == "{") { + return ((ch == '}') && (chNext == '}')); + } else { + return false; + } +} + +class PhpNumberState { + enum NumberBase { BASE_10 = 0, BASE_2, BASE_8, BASE_16 }; + static constexpr const char *const digitList[] = { "_0123456789", "_01", "_01234567", "_0123456789abcdefABCDEF" }; + + NumberBase base = BASE_10; + bool decimalPart = false; + bool exponentPart = false; + bool invalid = false; + bool finished = false; + + bool leadingZero = false; + bool invalidBase8 = false; + + bool betweenDigits = false; + bool decimalChar = false; + bool exponentChar = false; + +public: + [[nodiscard]] bool isInvalid() const noexcept { return invalid; } + [[nodiscard]] bool isFinished() const noexcept { return finished; } + + bool init(int ch, int chPlus1, int chPlus2) noexcept { + base = BASE_10; + decimalPart = false; + exponentPart = false; + invalid = false; + finished = false; + + leadingZero = false; + invalidBase8 = false; + + betweenDigits = false; + decimalChar = false; + exponentChar = false; + + if (ch == '.' && strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr) { + decimalPart = true; + betweenDigits = true; + } else if (ch == '0' && (chPlus1 == 'b' || chPlus1 == 'B')) { + base = BASE_2; + } else if (ch == '0' && (chPlus1 == 'o' || chPlus1 == 'O')) { + base = BASE_8; + } else if (ch == '0' && (chPlus1 == 'x' || chPlus1 == 'X')) { + base = BASE_16; + } else if (strchr(digitList[BASE_10] + !betweenDigits, ch) != nullptr) { + leadingZero = ch == '0'; + betweenDigits = true; + check(chPlus1, chPlus2); + if (finished && leadingZero) { + // single zero should be base 10 + base = BASE_10; + } + } else { + return false; + } + return true; + } + + bool check(int ch, int chPlus1) noexcept { + if (strchr(digitList[base] + !betweenDigits, ch) != nullptr) { + if (leadingZero) { + invalidBase8 = invalidBase8 || strchr(digitList[BASE_8] + !betweenDigits, ch) == nullptr; + } + + betweenDigits = ch != '_'; + decimalChar = false; + exponentChar = false; + } else if (ch == '_') { + invalid = true; + + betweenDigits = false; + decimalChar = false; + // exponentChar is unchanged + } else if (base == BASE_10 && ch == '.' && ( + !(decimalPart || exponentPart) || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr) + ) { + invalid = invalid || !betweenDigits || decimalPart || exponentPart; + decimalPart = true; + + betweenDigits = false; + decimalChar = true; + exponentChar = false; + } else if (base == BASE_10 && (ch == 'e' || ch == 'E')) { + invalid = invalid || !(betweenDigits || decimalChar) || exponentPart; + exponentPart = true; + + betweenDigits = false; + decimalChar = false; + exponentChar = true; + } else if (base == BASE_10 && (ch == '-' || ch == '+') && exponentChar) { + invalid = invalid || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) == nullptr; + + betweenDigits = false; + decimalChar = false; + // exponentChar is unchanged + } else if (IsPhpWordChar(ch)) { + invalid = true; + + betweenDigits = false; + decimalChar = false; + exponentChar = false; + } else { + invalid = invalid || !(betweenDigits || decimalChar); + finished = true; + if (base == BASE_10 && leadingZero && !decimalPart && !exponentPart) { + base = BASE_8; + invalid = invalid || invalidBase8; + } + } + return finished; + } +}; + +constexpr bool isPHPStringState(int state) noexcept { + return + (state == SCE_HPHP_HSTRING) || + (state == SCE_HPHP_SIMPLESTRING) || + (state == SCE_HPHP_HSTRING_VARIABLE) || + (state == SCE_HPHP_COMPLEX_VARIABLE); +} + +enum class AllowPHP : int { + None, // No PHP + PHP, // { + explicit OptionSetHTML(bool isPHPScript_) { + + DefineProperty("asp.default.language", &OptionsHTML::aspDefaultLanguage, + "Script in ASP code is initially assumed to be in JavaScript. " + "To change this to VBScript set asp.default.language to 2. Python is 3."); + + DefineProperty("html.tags.case.sensitive", &OptionsHTML::caseSensitive, + "For XML and HTML, setting this property to 1 will make tags match in a case " + "sensitive way which is the expected behaviour for XML and XHTML."); + + DefineProperty("lexer.xml.allow.scripts", &OptionsHTML::allowScripts, + "Set to 0 to disable scripts in XML."); + + DefineProperty("lexer.xml.allow.php", &OptionsHTML::allowPHPinXML, + "Set to 0 to disable PHP in XML, 1 to accept '", + 12, "SCE_H_XMLSTART", "identifier", "XML identifier start ''", + 14, "SCE_H_SCRIPT", "error", "Internal state which should never be visible", + 15, "SCE_H_ASP", "preprocessor", "ASP <% ... %>", + 16, "SCE_H_ASPAT", "preprocessor", "ASP <% ... %>", + 17, "SCE_H_CDATA", "literal", "CDATA", + 18, "SCE_H_QUESTION", "preprocessor", "PHP", + 19, "SCE_H_VALUE", "literal string", "Unquoted values", + 20, "SCE_H_XCCOMMENT", "comment", "ASP.NET, JSP Comment <%-- ... --%>", + 21, "SCE_H_SGML_DEFAULT", "default", "SGML tags ", + 22, "SCE_H_SGML_COMMAND", "preprocessor", "SGML command", + 23, "SCE_H_SGML_1ST_PARAM", "preprocessor", "SGML 1st param", + 24, "SCE_H_SGML_DOUBLESTRING", "literal string", "SGML double string", + 25, "SCE_H_SGML_SIMPLESTRING", "literal string", "SGML single string", + 26, "SCE_H_SGML_ERROR", "error", "SGML error", + 27, "SCE_H_SGML_SPECIAL", "literal", "SGML special (#XXXX type)", + 28, "SCE_H_SGML_ENTITY", "literal", "SGML entity", + 29, "SCE_H_SGML_COMMENT", "comment", "SGML comment", + 30, "SCE_H_SGML_1ST_PARAM_COMMENT", "error comment", "SGML first parameter - lexer internal. It is an error if any text is in this style.", + 31, "SCE_H_SGML_BLOCK_DEFAULT", "default", "SGML block", + 32, "", "predefined", "", + 33, "", "predefined", "", + 34, "", "predefined", "", + 35, "", "predefined", "", + 36, "", "predefined", "", + 37, "", "predefined", "", + 38, "", "predefined", "", + 39, "", "predefined", "", + 40, "SCE_HJ_START", "client javascript default", "JS Start - allows eol filled background to not start on same line as SCRIPT tag", + 41, "SCE_HJ_DEFAULT", "client javascript default", "JS Default", + 42, "SCE_HJ_COMMENT", "client javascript comment", "JS Comment", + 43, "SCE_HJ_COMMENTLINE", "client javascript comment line", "JS Line Comment", + 44, "SCE_HJ_COMMENTDOC", "client javascript comment documentation", "JS Doc comment", + 45, "SCE_HJ_NUMBER", "client javascript literal numeric", "JS Number", + 46, "SCE_HJ_WORD", "client javascript identifier", "JS Word", + 47, "SCE_HJ_KEYWORD", "client javascript keyword", "JS Keyword", + 48, "SCE_HJ_DOUBLESTRING", "client javascript literal string", "JS Double quoted string", + 49, "SCE_HJ_SINGLESTRING", "client javascript literal string", "JS Single quoted string", + 50, "SCE_HJ_SYMBOLS", "client javascript operator", "JS Symbols", + 51, "SCE_HJ_STRINGEOL", "client javascript error literal string", "JavaScript EOL", + 52, "SCE_HJ_REGEX", "client javascript literal regex", "JavaScript RegEx", + 53, "", "unused", "", + 54, "", "unused", "", + 55, "SCE_HJA_START", "server javascript default", "JS Start - allows eol filled background to not start on same line as SCRIPT tag", + 56, "SCE_HJA_DEFAULT", "server javascript default", "JS Default", + 57, "SCE_HJA_COMMENT", "server javascript comment", "JS Comment", + 58, "SCE_HJA_COMMENTLINE", "server javascript comment line", "JS Line Comment", + 59, "SCE_HJA_COMMENTDOC", "server javascript comment documentation", "JS Doc comment", + 60, "SCE_HJA_NUMBER", "server javascript literal numeric", "JS Number", + 61, "SCE_HJA_WORD", "server javascript identifier", "JS Word", + 62, "SCE_HJA_KEYWORD", "server javascript keyword", "JS Keyword", + 63, "SCE_HJA_DOUBLESTRING", "server javascript literal string", "JS Double quoted string", + 64, "SCE_HJA_SINGLESTRING", "server javascript literal string", "JS Single quoted string", + 65, "SCE_HJA_SYMBOLS", "server javascript operator", "JS Symbols", + 66, "SCE_HJA_STRINGEOL", "server javascript error literal string", "JavaScript EOL", + 67, "SCE_HJA_REGEX", "server javascript literal regex", "JavaScript RegEx", + 68, "", "unused", "", + 69, "", "unused", "", + 70, "SCE_HB_START", "client basic default", "Start", + 71, "SCE_HB_DEFAULT", "client basic default", "Default", + 72, "SCE_HB_COMMENTLINE", "client basic comment line", "Comment", + 73, "SCE_HB_NUMBER", "client basic literal numeric", "Number", + 74, "SCE_HB_WORD", "client basic keyword", "KeyWord", + 75, "SCE_HB_STRING", "client basic literal string", "String", + 76, "SCE_HB_IDENTIFIER", "client basic identifier", "Identifier", + 77, "SCE_HB_STRINGEOL", "client basic literal string", "Unterminated string", + 78, "", "unused", "", + 79, "", "unused", "", + 80, "SCE_HBA_START", "server basic default", "Start", + 81, "SCE_HBA_DEFAULT", "server basic default", "Default", + 82, "SCE_HBA_COMMENTLINE", "server basic comment line", "Comment", + 83, "SCE_HBA_NUMBER", "server basic literal numeric", "Number", + 84, "SCE_HBA_WORD", "server basic keyword", "KeyWord", + 85, "SCE_HBA_STRING", "server basic literal string", "String", + 86, "SCE_HBA_IDENTIFIER", "server basic identifier", "Identifier", + 87, "SCE_HBA_STRINGEOL", "server basic literal string", "Unterminated string", + 88, "", "unused", "", + 89, "", "unused", "", + 90, "SCE_HP_START", "client python default", "Embedded Python", + 91, "SCE_HP_DEFAULT", "client python default", "Embedded Python", + 92, "SCE_HP_COMMENTLINE", "client python comment line", "Comment", + 93, "SCE_HP_NUMBER", "client python literal numeric", "Number", + 94, "SCE_HP_STRING", "client python literal string", "String", + 95, "SCE_HP_CHARACTER", "client python literal string character", "Single quoted string", + 96, "SCE_HP_WORD", "client python keyword", "Keyword", + 97, "SCE_HP_TRIPLE", "client python literal string", "Triple quotes", + 98, "SCE_HP_TRIPLEDOUBLE", "client python literal string", "Triple double quotes", + 99, "SCE_HP_CLASSNAME", "client python identifier", "Class name definition", + 100, "SCE_HP_DEFNAME", "client python identifier", "Function or method name definition", + 101, "SCE_HP_OPERATOR", "client python operator", "Operators", + 102, "SCE_HP_IDENTIFIER", "client python identifier", "Identifiers", + 103, "", "unused", "", + 104, "SCE_HPHP_COMPLEX_VARIABLE", "server php identifier", "PHP complex variable", + 105, "SCE_HPA_START", "server python default", "ASP Python", + 106, "SCE_HPA_DEFAULT", "server python default", "ASP Python", + 107, "SCE_HPA_COMMENTLINE", "server python comment line", "Comment", + 108, "SCE_HPA_NUMBER", "server python literal numeric", "Number", + 109, "SCE_HPA_STRING", "server python literal string", "String", + 110, "SCE_HPA_CHARACTER", "server python literal string character", "Single quoted string", + 111, "SCE_HPA_WORD", "server python keyword", "Keyword", + 112, "SCE_HPA_TRIPLE", "server python literal string", "Triple quotes", + 113, "SCE_HPA_TRIPLEDOUBLE", "server python literal string", "Triple double quotes", + 114, "SCE_HPA_CLASSNAME", "server python identifier", "Class name definition", + 115, "SCE_HPA_DEFNAME", "server python identifier", "Function or method name definition", + 116, "SCE_HPA_OPERATOR", "server python operator", "Operators", + 117, "SCE_HPA_IDENTIFIER", "server python identifier", "Identifiers", + 118, "SCE_HPHP_DEFAULT", "server php default", "Default", + 119, "SCE_HPHP_HSTRING", "server php literal string", "Double quoted String", + 120, "SCE_HPHP_SIMPLESTRING", "server php literal string", "Single quoted string", + 121, "SCE_HPHP_WORD", "server php keyword", "Keyword", + 122, "SCE_HPHP_NUMBER", "server php literal numeric", "Number", + 123, "SCE_HPHP_VARIABLE", "server php identifier", "Variable", + 124, "SCE_HPHP_COMMENT", "server php comment", "Comment", + 125, "SCE_HPHP_COMMENTLINE", "server php comment line", "One line comment", + 126, "SCE_HPHP_HSTRING_VARIABLE", "server php literal string identifier", "PHP variable in double quoted string", + 127, "SCE_HPHP_OPERATOR", "server php operator", "PHP operator", +}; + +const LexicalClass lexicalClassesXML[] = { + // Lexer.Secondary XML SCLEX_XML SCE_H_: + 0, "SCE_H_DEFAULT", "default", "Default", + 1, "SCE_H_TAG", "tag", "Tags", + 2, "SCE_H_TAGUNKNOWN", "error tag", "Unknown Tags", + 3, "SCE_H_ATTRIBUTE", "attribute", "Attributes", + 4, "SCE_H_ERRORATTRIBUTEUNKNOWN", "error attribute", "Unknown Attributes", + 5, "SCE_H_NUMBER", "literal numeric", "Numbers", + 6, "SCE_H_DOUBLESTRING", "literal string", "Double quoted strings", + 7, "SCE_H_SINGLESTRING", "literal string", "Single quoted strings", + 8, "SCE_H_OTHER", "tag operator", "Other inside tag, including space and '='", + 9, "SCE_H_COMMENT", "comment", "Comment", + 10, "SCE_H_ENTITY", "literal", "Entities", + 11, "SCE_H_TAGEND", "tag", "XML style tag ends '/>'", + 12, "SCE_H_XMLSTART", "identifier", "XML identifier start ''", + 14, "", "unused", "", + 15, "", "unused", "", + 16, "", "unused", "", + 17, "SCE_H_CDATA", "literal", "CDATA", + 18, "SCE_H_QUESTION", "preprocessor", "Question", + 19, "SCE_H_VALUE", "literal string", "Unquoted Value", + 20, "", "unused", "", + 21, "SCE_H_SGML_DEFAULT", "default", "SGML tags ", + 22, "SCE_H_SGML_COMMAND", "preprocessor", "SGML command", + 23, "SCE_H_SGML_1ST_PARAM", "preprocessor", "SGML 1st param", + 24, "SCE_H_SGML_DOUBLESTRING", "literal string", "SGML double string", + 25, "SCE_H_SGML_SIMPLESTRING", "literal string", "SGML single string", + 26, "SCE_H_SGML_ERROR", "error", "SGML error", + 27, "SCE_H_SGML_SPECIAL", "literal", "SGML special (#XXXX type)", + 28, "SCE_H_SGML_ENTITY", "literal", "SGML entity", + 29, "SCE_H_SGML_COMMENT", "comment", "SGML comment", + 30, "", "unused", "", + 31, "SCE_H_SGML_BLOCK_DEFAULT", "default", "SGML block", +}; + +const char * const tagsThatDoNotFold[] = { + "area", + "base", + "basefont", + "br", + "col", + "command", + "embed", + "frame", + "hr", + "img", + "input", + "isindex", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr" +}; + +} + +class LexerHTML : public DefaultLexer { + bool isXml; + bool isPHPScript; + WordList keywordsHTML; + WordList keywordsJS; + WordList keywordsVB; + WordList keywordsPy; + WordList keywordsPHP; + WordList keywordsSGML; // SGML (DTD) keywords + OptionsHTML options; + OptionSetHTML osHTML; + std::set nonFoldingTags; + SubStyles subStyles{styleSubable,SubStylesHTML,SubStylesAvailable,0}; +public: + explicit LexerHTML(bool isXml_, bool isPHPScript_) : + DefaultLexer( + isXml_ ? "xml" : (isPHPScript_ ? "phpscript" : "hypertext"), + isXml_ ? SCLEX_XML : (isPHPScript_ ? SCLEX_PHPSCRIPT : SCLEX_HTML), + isXml_ ? lexicalClassesXML : lexicalClassesHTML, + isXml_ ? std::size(lexicalClassesXML) : std::size(lexicalClassesHTML)), + isXml(isXml_), + isPHPScript(isPHPScript_), + osHTML(isPHPScript_), + nonFoldingTags(std::begin(tagsThatDoNotFold), std::end(tagsThatDoNotFold)) { + } + ~LexerHTML() override { + } + void SCI_METHOD Release() override { + delete this; + } + const char *SCI_METHOD PropertyNames() override { + return osHTML.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osHTML.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) override { + return osHTML.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char *key) override { + return osHTML.PropertyGet(key); + } + const char *SCI_METHOD DescribeWordListSets() override { + return osHTML.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + // No Fold as all folding performs in Lex. + + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) override { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) override { + return subStyles.Length(styleBase); + } + int SCI_METHOD StyleFromSubStyle(int subStyle) override { + const int styleBase = subStyles.BaseStyle(subStyle); + return styleBase; + } + int SCI_METHOD PrimaryStyleFromStyle(int style) override { + return style; + } + void SCI_METHOD FreeSubStyles() override { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override { + const int styleBase = subStyles.BaseStyle(style); + const bool lowerCase = AnyOf(styleBase, SCE_H_TAG, SCE_H_ATTRIBUTE, SCE_HB_WORD); + subStyles.SetIdentifiers(style, identifiers, lowerCase); + } + int SCI_METHOD DistanceToSecondaryStyles() override { + return 0; + } + const char *SCI_METHOD GetSubStyleBases() override { + return styleSubable; + } + + static ILexer5 *LexerFactoryHTML() { + return new LexerHTML(false, false); + } + static ILexer5 *LexerFactoryXML() { + return new LexerHTML(true, false); + } + static ILexer5 *LexerFactoryPHPScript() { + return new LexerHTML(false, true); + } +}; + +Sci_Position SCI_METHOD LexerHTML::PropertySet(const char *key, const char *val) { + if (osHTML.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerHTML::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + bool lowerCase = false; + switch (n) { + case 0: + wordListN = &keywordsHTML; + lowerCase = true; + break; + case 1: + wordListN = &keywordsJS; + break; + case 2: + wordListN = &keywordsVB; + lowerCase = true; + break; + case 3: + wordListN = &keywordsPy; + break; + case 4: + wordListN = &keywordsPHP; + break; + case 5: + wordListN = &keywordsSGML; + break; + default: + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + if (wordListN->Set(wl, lowerCase)) { + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + Accessor styler(pAccess, nullptr); + + const WordClassifier &classifierTags = subStyles.Classifier(SCE_H_TAG); + const WordClassifier &classifierAttributes = subStyles.Classifier(SCE_H_ATTRIBUTE); + const WordClassifier &classifierJavaScript = subStyles.Classifier(SCE_HJ_WORD); + const WordClassifier &classifierJavaScriptServer = subStyles.Classifier(SCE_HJA_WORD); + const WordClassifier &classifierBasic = subStyles.Classifier(SCE_HB_WORD); + const WordClassifier &classifierPython = subStyles.Classifier(SCE_HP_WORD); + const WordClassifier &classifierPHP = subStyles.Classifier(SCE_HPHP_WORD); + + if (isPHPScript && (startPos == 0)) { + initStyle = SCE_HPHP_DEFAULT; + } + styler.StartAt(startPos); + std::string lastTag; + std::string prevWord; + PhpNumberState phpNumber; + std::string phpStringDelimiter; + int StateToPrint = initStyle; + int state = stateForPrintState(StateToPrint); + std::string makoBlockType; + int makoComment = 0; + std::string djangoBlockType; + // If inside a tag, it may be a script tag, so reread from the start of line starting tag to ensure any language tags are seen + if (InTagState(state)) { + while ((startPos > 0) && (InTagState(styler.StyleIndexAt(startPos - 1)))) { + const Sci_Position backLineStart = styler.LineStart(styler.GetLine(startPos-1)); + length += startPos - backLineStart; + startPos = backLineStart; + } + state = SCE_H_DEFAULT; + } + // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState + if (isPHPStringState(state)) { + while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) { + startPos--; + length++; + state = styler.StyleIndexAt(startPos); + } + if (startPos == 0) + state = SCE_H_DEFAULT; + } + styler.StartAt(startPos); + + /* Nothing handles getting out of these, so we need not start in any of them. + * As we're at line start and they can't span lines, we'll re-detect them anyway */ + switch (state) { + case SCE_H_QUESTION: + case SCE_H_XMLSTART: + case SCE_H_XMLEND: + case SCE_H_ASP: + state = SCE_H_DEFAULT; + break; + default: + break; + } + + Sci_Position lineCurrent = styler.GetLine(startPos); + int lineState; + if (lineCurrent > 0) { + lineState = styler.GetLineState(lineCurrent-1); + } else { + // Default client and ASP scripting language is JavaScript + lineState = eScriptJS << 8; + lineState |= options.aspDefaultLanguage << 4; + } + script_mode inScriptType = static_cast((lineState >> 0) & 0x03); // 2 bits of scripting mode + + bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag + bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag + bool tagDontFold = false; //some HTML tags should not be folded + script_type aspScript = static_cast((lineState >> 4) & 0x0F); // 4 bits of script name + script_type clientScript = static_cast((lineState >> 8) & 0x0F); // 4 bits of script name + int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state + bool isLanguageType = (lineState >> 20) & 1; // type or language attribute for script tag + + script_type scriptLanguage = ScriptOfState(state); + // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment + if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) { + scriptLanguage = eScriptComment; + } + script_type beforeLanguage = ScriptOfState(beforePreProc); + const bool foldHTML = options.foldHTML; + const bool fold = foldHTML && options.fold; + const bool foldHTMLPreprocessor = foldHTML && options.foldHTMLPreprocessor; + const bool foldCompact = options.foldCompact; + const bool foldComment = fold && options.foldComment; + const bool foldHeredoc = fold && options.foldHeredoc; + const bool foldXmlAtTagOpen = isXml && fold && options.foldXmlAtTagOpen; + const bool caseSensitive = options.caseSensitive; + const bool allowScripts = options.allowScripts; + const AllowPHP allowPHP = isXml ? options.allowPHPinXML : options.allowPHPinHTML; + const bool isMako = options.isMako; + const bool isDjango = options.isDjango; + const bool allowASP = (isXml ? options.allowASPinXML : options.allowASPinHTML) && !isMako && !isDjango; + const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", true); + const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", true); + const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", true); + // TODO: also handle + and - (except if they're part of ++ or --) and return keywords + const CharacterSet setOKBeforeJSRE(CharacterSet::setNone, "([{=,:;!%^&*|?~> "); + // Only allow [A-Za-z0-9.#-_:] in entities + const CharacterSet setEntity(CharacterSet::setAlphaNum, ".#-_:"); + + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + Sci_Position visibleChars = 0; + int lineStartVisibleChars = 0; + + int chPrev = ' '; + int ch = ' '; + int chPrevNonWhite = ' '; + // look back to set chPrevNonWhite properly for better regex colouring + if (scriptLanguage == eScriptJS && startPos > 0) { + Sci_Position back = startPos; + int style = 0; + while (--back) { + style = styler.StyleIndexAt(back); + if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC) + // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE + break; + } + if (style == SCE_HJ_SYMBOLS) { + chPrevNonWhite = SafeGetUnsignedCharAt(styler, back); + } + } + + styler.StartSegment(startPos); + const Sci_Position lengthDoc = startPos + length; + for (Sci_Position i = startPos; i < lengthDoc; i++) { + const int chPrev2 = chPrev; + chPrev = ch; + if (!IsASpace(ch) && state != SCE_HJ_COMMENT && + state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC) + chPrevNonWhite = ch; + ch = static_cast(styler[i]); + int chNext = SafeGetUnsignedCharAt(styler, i + 1); + const int chNext2 = SafeGetUnsignedCharAt(styler, i + 2); + + // Handle DBCS codepages + if (styler.IsLeadByte(static_cast(ch))) { + chPrev = ' '; + i += 1; + continue; + } + + if ((!IsASpace(ch) || !foldCompact) && fold) + visibleChars++; + if (!IsASpace(ch)) + lineStartVisibleChars++; + + // decide what is the current state to print (depending of the script tag) + StateToPrint = statePrintForState(state, inScriptType); + + // handle script folding + if (fold) { + switch (scriptLanguage) { + case eScriptJS: + case eScriptPHP: + //not currently supported case eScriptVBS: + + if (!AnyOf(state, SCE_HPHP_COMMENT, SCE_HPHP_COMMENTLINE, SCE_HJ_REGEX, SCE_HJ_COMMENT, SCE_HJ_COMMENTLINE, SCE_HJ_COMMENTDOC) && + !isStringState(state)) { + //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); + //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { + if (ch == '#') { + Sci_Position j = i + 1; + while ((j < lengthDoc) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelCurrent++; + } else if (styler.Match(j, "end")) { + levelCurrent--; + } + } else if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { + levelCurrent += (((ch == '{') || (ch == '/')) ? 1 : -1); + } + } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTDOC)) && foldComment && (ch == '*') && (chNext == '/')) { + levelCurrent--; + } + break; + case eScriptPython: + if (state != SCE_HP_COMMENTLINE && !isMako) { + if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) { + levelCurrent++; + } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) { + // check if the number of tabs is lower than the level + constexpr int tabWidth = 8; + int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * tabWidth; + for (Sci_Position j = 0; Findlevel > 0; j++) { + const char chTmp = styler.SafeGetCharAt(i + j + 1); + if (chTmp == '\t') { + Findlevel -= tabWidth; + } else if (chTmp == ' ') { + Findlevel--; + } else { + break; + } + } + + if (Findlevel > 0) { + levelCurrent -= Findlevel / tabWidth; + if (Findlevel % tabWidth) + levelCurrent--; + } + } + } + break; + default: + break; + } + } + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // New line -> record any line state onto /next/ line + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + + styler.SetLevel(lineCurrent, lev); + visibleChars = 0; + levelPrev = levelCurrent; + } + styler.SetLineState(lineCurrent, + ((inScriptType & 0x03) << 0) | + ((tagOpened ? 1 : 0) << 2) | + ((tagClosing ? 1 : 0) << 3) | + ((aspScript & 0x0F) << 4) | + ((clientScript & 0x0F) << 8) | + ((beforePreProc & 0xFF) << 12) | + ((isLanguageType ? 1 : 0) << 20)); + lineCurrent++; + lineStartVisibleChars = 0; + } + + // handle start of Mako comment line + if (isMako && ch == '#' && chNext == '#') { + makoComment = 1; + state = SCE_HP_COMMENTLINE; + } + + // handle end of Mako comment line + else if (isMako && makoComment && (ch == '\r' || ch == '\n')) { + makoComment = 0; + styler.ColourTo(i - 1, StateToPrint); + if (scriptLanguage == eScriptPython) { + state = SCE_HP_DEFAULT; + } else { + state = SCE_H_DEFAULT; + } + } + // Allow falling through to mako handling code if newline is going to end a block + if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && + (!isMako || (makoBlockType != "%"))) { + } + // Ignore everything in mako comment until the line ends + else if (isMako && makoComment) { + } + + // generic end of script processing + else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { + // Check if it's the end of the script tag (or any other HTML tag) + switch (state) { + // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!) + case SCE_H_DOUBLESTRING: + case SCE_H_SINGLESTRING: + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide + // the end of script marker from some JS interpreters. + //case SCE_HB_COMMENTLINE: + case SCE_HBA_COMMENTLINE: + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJ_REGEX: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + break; + default : + // check if the closing tag is a script tag + if (const char *tag = + (state == SCE_HJ_COMMENTLINE || state == SCE_HB_COMMENTLINE || isXml) ? "script" : + state == SCE_H_COMMENT ? "comment" : nullptr) { + Sci_Position j = i + 2; + int chr; + do { + chr = static_cast(*tag++); + } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++))); + if (chr != 0) break; + } + // closing tag of the script (it's a closing HTML tag anyway) + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_TAGUNKNOWN; + inScriptType = eHtml; + scriptLanguage = eScriptNone; + clientScript = eScriptJS; + isLanguageType = false; + i += 2; + visibleChars += 2; + tagClosing = true; + if (foldXmlAtTagOpen) { + levelCurrent--; + } + continue; + } + } + + ///////////////////////////////////// + // handle the start of PHP pre-processor = Non-HTML + else if ((ch == '<') && (chNext == '?') && IsPHPEntryState(state) && IsPHPStart(allowPHP, styler, i)) { + beforeLanguage = scriptLanguage; + scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, isXml ? eScriptXML : eScriptPHP); + if ((scriptLanguage != eScriptPHP) && (isStringState(state) || (state==SCE_H_COMMENT))) continue; + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + i++; + visibleChars++; + i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6); + if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLSTART); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = StateForScript(scriptLanguage); + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + // Fold whole script, but not if the XML first tag (all XML-like tags in this case) + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent++; + } + // should be better + ch = SafeGetUnsignedCharAt(styler, i); + continue; + } + + // handle the start Mako template Python code + else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || + (lineStartVisibleChars == 1 && ch == '%') || + (lineStartVisibleChars == 1 && ch == '/' && chNext == '%') || + (ch == '$' && chNext == '{') || + (ch == '<' && chNext == '/' && chNext2 == '%'))) { + if (ch == '%' || ch == '/') + makoBlockType = "%"; + else if (ch == '$') + makoBlockType = "{"; + else if (chNext == '/') + makoBlockType = GetNextWord(styler, i+3); // Tag end: + else + makoBlockType = GetNextWord(styler, i+2); // Tag: <%tag...> + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + if (chNext == '/') { + i += 2; + visibleChars += 2; + } else if (ch != '%') { + i++; + visibleChars++; + } + state = SCE_HP_START; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + if (ch != '%' && ch != '$' && ch != '/') { + i += makoBlockType.length(); + visibleChars += makoBlockType.length(); + if (keywordsPy.InList(makoBlockType)) + styler.ColourTo(i, SCE_HP_WORD); + else + styler.ColourTo(i, SCE_H_TAGUNKNOWN); + } + + ch = SafeGetUnsignedCharAt(styler, i); + continue; + } + + // handle the start/end of Django comment + else if (isDjango && state != SCE_H_COMMENT && (ch == '{' && chNext == '#')) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + beforeLanguage = scriptLanguage; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + i += 1; + visibleChars += 1; + scriptLanguage = eScriptComment; + state = SCE_H_COMMENT; + styler.ColourTo(i, SCE_H_ASP); + ch = SafeGetUnsignedCharAt(styler, i); + continue; + } else if (isDjango && state == SCE_H_COMMENT && (ch == '#' && chNext == '}')) { + styler.ColourTo(i - 1, StateToPrint); + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + + // handle the start Django template code + else if (isDjango && scriptLanguage != eScriptPython && scriptLanguage != eScriptComment && (ch == '{' && (chNext == '%' || chNext == '{'))) { + if (chNext == '%') + djangoBlockType = "%"; + else + djangoBlockType = "{"; + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + i += 1; + visibleChars += 1; + state = SCE_HP_START; + beforeLanguage = scriptLanguage; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + + ch = SafeGetUnsignedCharAt(styler, i); + continue; + } + + // handle the start of ASP pre-processor = Non-HTML + else if ((ch == '<') && (chNext == '%') && allowASP && !isCommentASPState(state) && !isPHPStringState(state)) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + // fold whole script + if (foldHTMLPreprocessor) + levelCurrent++; + if (chNext2 == '@') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + state = SCE_H_ASPAT; + scriptLanguage = eScriptVBS; + } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) { + styler.ColourTo(i + 3, SCE_H_ASP); + state = SCE_H_XCCOMMENT; + scriptLanguage = eScriptVBS; + continue; + } else { + if (chNext2 == '=') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + } else { + i++; // place as if it was the next char treated + visibleChars++; + } + + state = StateForScript(aspScript); + scriptLanguage = aspScript; + } + styler.ColourTo(i, SCE_H_ASP); + // should be better + ch = SafeGetUnsignedCharAt(styler, i); + continue; + } + + ///////////////////////////////////// + // handle the start of SGML language (DTD) + else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) && + (chPrev == '<') && + (ch == '!') && + (StateToPrint != SCE_H_CDATA) && + (!isStringState(StateToPrint)) && + (!IsCommentState(StateToPrint)) && + (!IsScriptCommentState(StateToPrint))) { + beforePreProc = state; + styler.ColourTo(i - 2, StateToPrint); + if ((chNext == '-') && (chNext2 == '-')) { + state = SCE_H_COMMENT; // wait for a pending command + styler.ColourTo(i + 2, SCE_H_COMMENT); + i += 2; // follow styling after the -- + if (!isXml) { + // handle empty comment: , + // https://html.spec.whatwg.org/multipage/parsing.html#parse-error-abrupt-closing-of-empty-comment + chNext = SafeGetUnsignedCharAt(styler, i + 1); + if ((chNext == '>') || (chNext == '-' && SafeGetUnsignedCharAt(styler, i + 2) == '>')) { + if (chNext == '-') { + i += 1; + } + chPrev = '-'; + ch = '-'; + } + } + } else if (isWordCdata(i + 1, i + 7, styler)) { + state = SCE_H_CDATA; + } else { + styler.ColourTo(i, SCE_H_SGML_DEFAULT); // ') { + i++; + visibleChars++; + } else if ((makoBlockType == "%") && ch == '/') { + i++; + visibleChars++; + } + if ((makoBlockType != "%") || ch == '/') { + styler.ColourTo(i, SCE_H_ASP); + } + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = eScriptNone; + continue; + } + + // handle the end of Django template code + else if (isDjango && + ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && + isDjangoBlockEnd(ch, chNext, djangoBlockType)) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + if (state == SCE_HP_WORD) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywordsPy, classifierPython, styler, prevWord, inScriptType, isMako); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + + // handle the end of a pre-processor = Non-HTML + else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) && + ((chNext == '>') && isPreProcessorEndTag(state, ch))) || + ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + // Bounce out of any ASP mode + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywordsJS, classifierJavaScript, classifierJavaScriptServer, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), i - 1, keywordsVB, classifierBasic, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywordsPy, classifierPython, styler, prevWord, inScriptType, isMako); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywordsPHP, classifierPHP, styler); + break; + case SCE_H_XCCOMMENT: + styler.ColourTo(i - 1, state); + break; + default : + styler.ColourTo(i - 1, StateToPrint); + break; + } + if (scriptLanguage != eScriptSGML) { + i++; + visibleChars++; + } + if (ch == '%') + styler.ColourTo(i, SCE_H_ASP); + else if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLEND); + else if (scriptLanguage == eScriptSGML) + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + // Unfold all scripting languages, except for XML tag + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent--; + } + scriptLanguage = beforeLanguage; + continue; + } + ///////////////////////////////////// + + switch (state) { + case SCE_H_DEFAULT: + if (ch == '<') { + // in HTML, fold on tag open and unfold on tag close + tagOpened = true; + tagClosing = (chNext == '/'); + if (foldXmlAtTagOpen && !AnyOf(chNext, '/', '?', '!', '-', '%')) { + levelCurrent++; + } + if (foldXmlAtTagOpen && chNext == '/') { + levelCurrent--; + } + styler.ColourTo(i - 1, StateToPrint); + if (chNext != '!') + state = SCE_H_TAGUNKNOWN; + } else if (ch == '&') { + styler.ColourTo(i - 1, SCE_H_DEFAULT); + state = SCE_H_ENTITY; + } + break; + case SCE_H_SGML_DEFAULT: + case SCE_H_SGML_BLOCK_DEFAULT: +// if (scriptLanguage == eScriptSGMLblock) +// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; + + if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SIMPLESTRING; + } else if ((ch == '-') && (chPrev == '-')) { + if (static_cast(styler.GetStartSegment()) <= (i - 2)) { + styler.ColourTo(i - 2, StateToPrint); + } + state = SCE_H_SGML_COMMENT; + } else if (IsUpperOrLowerCase(ch) && (chPrev == '%')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_ENTITY; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SPECIAL; + } else if (ch == '[') { + styler.ColourTo(i - 1, StateToPrint); + scriptLanguage = eScriptSGMLblock; + state = SCE_H_SGML_BLOCK_DEFAULT; + } else if (ch == ']') { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i, StateToPrint); + scriptLanguage = eScriptSGML; + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_ERROR); + } + state = SCE_H_SGML_DEFAULT; + } else if (scriptLanguage == eScriptSGMLblock) { + if ((ch == '!') && (chPrev == '<')) { + styler.ColourTo(i - 2, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + state = SCE_H_SGML_COMMAND; + } else if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + } + } + break; + case SCE_H_SGML_COMMAND: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } else if (!issgmlwordchar(ch)) { + if (isWordHSGML(styler.GetStartSegment(), i - 1, keywordsSGML, styler)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_1ST_PARAM; + } else { + state = SCE_H_SGML_ERROR; + } + } + break; + case SCE_H_SGML_1ST_PARAM: + // wait for the beginning of the word + if ((ch == '-') && (chPrev == '-')) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT); + } + state = SCE_H_SGML_1ST_PARAM_COMMENT; + } else if (issgmlwordchar(ch)) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT); + } + // find the length of the word + Sci_Position size = 1; + while (setHTMLWord.Contains(SafeGetUnsignedCharAt(styler, i + size))) + size++; + styler.ColourTo(i + size - 1, StateToPrint); + i += size - 1; + visibleChars += size - 1; + ch = SafeGetUnsignedCharAt(styler, i); + if (scriptLanguage == eScriptSGMLblock) { + state = SCE_H_SGML_BLOCK_DEFAULT; + } else { + state = SCE_H_SGML_DEFAULT; + } + continue; + } + break; + case SCE_H_SGML_ERROR: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } + break; + case SCE_H_SGML_DOUBLESTRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_SIMPLESTRING: + if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_CDATA: + if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_COMMENT: + if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>' || (!isXml && ch == '!' && chNext == '>'))) { + // close HTML comment with --!> + // https://html.spec.whatwg.org/multipage/parsing.html#parse-error-incorrectly-closed-comment + if (ch == '!') { + i += 1; + } + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_SGML_1ST_PARAM_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, SCE_H_SGML_COMMENT); + state = SCE_H_SGML_1ST_PARAM; + } + break; + case SCE_H_SGML_SPECIAL: + if (!IsUpperCase(ch)) { + styler.ColourTo(i - 1, StateToPrint); + if (IsAlphaNumeric(ch)) { + state = SCE_H_SGML_ERROR; + } else { + state = SCE_H_SGML_DEFAULT; + } + } + break; + case SCE_H_SGML_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } else if (!(IsAlphaNumeric(ch)) && ch != '-' && ch != '.') { + styler.ColourTo(i, SCE_H_SGML_ERROR); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + } else if (!setEntity.Contains(ch)) { + styler.ColourTo(i-1, SCE_H_TAGUNKNOWN); + state = SCE_H_DEFAULT; + if (!isLineEnd(ch)) { + // Retreat one byte so the character that is invalid inside entity + // may start something else like a tag. + --i; + continue; + } + } + break; + case SCE_H_TAGUNKNOWN: + if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) { + int eClass = classifyTagHTML(styler.GetStartSegment(), + i - 1, keywordsHTML, classifierTags, styler, tagDontFold, caseSensitive, isXml, allowScripts, nonFoldingTags, lastTag); + if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) { + if (!tagClosing) { + inScriptType = eNonHtmlScript; + scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment; + } else { + scriptLanguage = eScriptNone; + } + isLanguageType = false; + eClass = SCE_H_TAG; + } + if (ch == '>') { + styler.ColourTo(i, eClass); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!(foldXmlAtTagOpen || tagDontFold)) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '/' && chNext == '>') { + if (eClass == SCE_H_TAGUNKNOWN) { + styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN); + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + } + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + if (foldXmlAtTagOpen) { + levelCurrent--; + } + } else { + if (eClass != SCE_H_TAGUNKNOWN) { + if (eClass == SCE_H_SGML_DEFAULT) { + state = SCE_H_SGML_DEFAULT; + } else { + state = SCE_H_OTHER; + } + } + } + } + break; + case SCE_H_ATTRIBUTE: + if (!setAttributeContinue.Contains(ch)) { + isLanguageType = classifyAttribHTML(inScriptType, styler.GetStartSegment(), i - 1, keywordsHTML, classifierAttributes, styler, lastTag); + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!(foldXmlAtTagOpen || tagDontFold)) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '=') { + styler.ColourTo(i, SCE_H_OTHER); + state = SCE_H_VALUE; + } else { + state = SCE_H_OTHER; + } + } + break; + case SCE_H_OTHER: + if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!(foldXmlAtTagOpen || tagDontFold)) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SINGLESTRING; + } else if (ch == '=') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_VALUE; + } else if (ch == '/' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + if (foldXmlAtTagOpen) { + levelCurrent--; + } + } else if (ch == '?' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_XMLEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + } else if (setHTMLWord.Contains(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_ATTRIBUTE; + } + break; + case SCE_H_DOUBLESTRING: + if (ch == '\"') { + if (isLanguageType) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + clientScript = scriptLanguage; + isLanguageType = false; + } + styler.ColourTo(i, SCE_H_DOUBLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_SINGLESTRING: + if (ch == '\'') { + if (isLanguageType) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + clientScript = scriptLanguage; + isLanguageType = false; + } + styler.ColourTo(i, SCE_H_SINGLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_VALUE: + if (!setHTMLWord.Contains(ch)) { + if (ch == '\"' && chPrev == '=') { + // Should really test for being first character + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'' && chPrev == '=') { + state = SCE_H_SINGLESTRING; + } else { + if (IsNumberChar(styler[styler.GetStartSegment()])) { + styler.ColourTo(i - 1, SCE_H_NUMBER); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else { + state = SCE_H_OTHER; + } + } + } + break; + case SCE_HJ_DEFAULT: + case SCE_HJ_START: + case SCE_HJ_SYMBOLS: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_WORD; + } else if (ch == '/' && chNext == '*') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + if (chNext2 == '/') { + // Eat the * so it isn't used for the end of the comment + i++; + } + } else if (ch == '/' && chNext == '/') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if (ch == '/' && setOKBeforeJSRE.Contains(chPrevNonWhite)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_REGEX; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HJ_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywordsJS, + classifierJavaScript, classifierJavaScriptServer, styler, inScriptType); + //styler.ColourTo(i - 1, eHTJSKeyword); + state = SCE_HJ_DEFAULT; + if (ch == '/' && chNext == '*') { + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType)); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_DOUBLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\"') { + styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + if (chPrev != '\\' && (chPrev2 != '\\' || chPrev != '\r' || ch != '\n')) { + state = SCE_HJ_STRINGEOL; + } + } + break; + case SCE_HJ_SINGLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\'') { + styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + if (chPrev != '\\' && (chPrev2 != '\\' || chPrev != '\r' || ch != '\n')) { + state = SCE_HJ_STRINGEOL; + } + } + break; + case SCE_HJ_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } + break; + case SCE_HJ_REGEX: + if (ch == '\r' || ch == '\n' || ch == '/') { + if (ch == '/') { + while (IsLowerCase(chNext)) { // gobble regex flags + i++; + ch = chNext; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } + } + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (ch == '\\') { + // Gobble up the quoted character + if (chNext == '\\' || chNext == '/') { + i++; + ch = chNext; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } + } + break; + case SCE_HB_DEFAULT: + case SCE_HB_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_WORD; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HB_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + } + break; + case SCE_HB_WORD: + if (!IsAWordChar(ch)) { + state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywordsVB, classifierBasic, styler, inScriptType); + if (state == SCE_HB_DEFAULT) { + if (ch == '\"') { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } + } + } + break; + case SCE_HB_STRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRINGEOL; + } + break; + case SCE_HB_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HB_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HP_DEFAULT: + case SCE_HP_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_WORD; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } else { + // state = statePrintForState(SCE_HP_STRING,inScriptType); + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HP_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + } + break; + case SCE_HP_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywordsPy, classifierPython, styler, prevWord, inScriptType, isMako); + state = SCE_HP_DEFAULT; + if (ch == '#') { + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } else { + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } + } + break; + case SCE_HP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_STRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_CHARACTER: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = SafeGetUnsignedCharAt(styler, i + 1); + } + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLE: + if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLEDOUBLE: + if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + ///////////// start - PHP state handling + case SCE_HPHP_WORD: + if (!IsPhpWordChar(ch)) { + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywordsPHP, classifierPHP, styler); + if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#' && chNext != '[') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + phpStringDelimiter = "\""; + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, i + 3, lengthDoc, styler, isSimpleString); + if (!phpStringDelimiter.empty()) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + phpStringDelimiter = "\'"; + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else { + state = SCE_HPHP_DEFAULT; + } + } + break; + case SCE_HPHP_NUMBER: + if (phpNumber.check(chNext, chNext2)) { + styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, SCE_HPHP_VARIABLE); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENT: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_HSTRING: + if (ch == '\\' && ((phpStringDelimiter == "\"") || chNext == '$' || chNext == '{')) { + // skip the next char + i++; + } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{')) + && IsPhpWordStart(chNext2)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_COMPLEX_VARIABLE; + } else if (ch == '$' && IsPhpWordStart(chNext)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_HSTRING_VARIABLE; + } else if (styler.Match(i, phpStringDelimiter.c_str())) { + if (phpStringDelimiter == "\"") { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } else if (lineStartVisibleChars == 1) { + const int psdLength = static_cast(phpStringDelimiter.length()); + if (!IsPhpWordChar(styler.SafeGetCharAt(i + psdLength))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + } + break; + case SCE_HPHP_SIMPLESTRING: + if (phpStringDelimiter == "\'") { + if (ch == '\\') { + // skip the next char + i++; + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + } else if (lineStartVisibleChars == 1 && styler.Match(i, phpStringDelimiter.c_str())) { + const int psdLength = static_cast(phpStringDelimiter.length()); + if (!IsPhpWordChar(styler.SafeGetCharAt(i + psdLength))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + break; + case SCE_HPHP_HSTRING_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_COMPLEX_VARIABLE: + if (ch == '}') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_OPERATOR: + case SCE_HPHP_DEFAULT: + styler.ColourTo(i - 1, StateToPrint); + if (phpNumber.init(ch, chNext, chNext2)) { + if (phpNumber.isFinished()) { + styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER); + state = SCE_HPHP_DEFAULT; + } else { + state = SCE_HPHP_NUMBER; + } + } else if (IsAWordStart(ch)) { + state = SCE_HPHP_WORD; + } else if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#' && chNext != '[') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + phpStringDelimiter = "\""; + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, i + 3, lengthDoc, styler, isSimpleString); + if (!phpStringDelimiter.empty()) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + phpStringDelimiter = "\'"; + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) { + state = SCE_HPHP_DEFAULT; + } + break; + ///////////// end - PHP state handling + } + + // Some of the above terminated their lexeme but since the same character starts + // the same class again, only reenter if non empty segment. + + const bool nonEmptySegment = i >= static_cast(styler.GetStartSegment()); + if (state == SCE_HB_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HB_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HB_DEFAULT); + } + } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HBA_STRING; + } else if (ch == '\'') { + state = SCE_HBA_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HBA_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HBA_DEFAULT); + } + } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded + if (ch == '/' && chNext == '*') { + if (styler.SafeGetCharAt(i + 2) == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HJ_DOUBLESTRING; + } else if ((ch == '\'') && (nonEmptySegment)) { + state = SCE_HJ_SINGLESTRING; + } else if (IsAWordStart(ch)) { + state = SCE_HJ_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + } + } + } + + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywordsJS, + classifierJavaScript, classifierJavaScriptServer, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywordsVB, classifierBasic, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywordsPy, classifierPython, styler, prevWord, inScriptType, isMako); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywordsPHP, classifierPHP, styler); + break; + default: + StateToPrint = statePrintForState(state, inScriptType); + if (static_cast(styler.GetStartSegment()) < lengthDoc) + styler.ColourTo(lengthDoc - 1, StateToPrint); + break; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + const int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + } + styler.Flush(); +} + +extern const LexerModule lmHTML(SCLEX_HTML, LexerHTML::LexerFactoryHTML, "hypertext", htmlWordListDesc); +extern const LexerModule lmXML(SCLEX_XML, LexerHTML::LexerFactoryXML, "xml", htmlWordListDesc); +extern const LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, LexerHTML::LexerFactoryPHPScript, "phpscript", phpscriptWordListDesc); diff --git a/src/lexilla/lexers/LexHaskell.cxx b/src/lexilla/lexers/LexHaskell.cxx new file mode 100644 index 000000000..9fd382883 --- /dev/null +++ b/src/lexilla/lexers/LexHaskell.cxx @@ -0,0 +1,1119 @@ +/****************************************************************** + * LexHaskell.cxx + * + * A haskell lexer for the scintilla code control. + * Some stuff "lended" from LexPython.cxx and LexCPP.cxx. + * External lexer stuff inspired from the caml external lexer. + * Folder copied from Python's. + * + * Written by Tobias Engvall - tumm at dtek dot chalmers dot se + * + * Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com + * + * Improved by kudah + * + * TODO: + * * A proper lexical folder to fold group declarations, comments, pragmas, + * #ifdefs, explicit layout, lists, tuples, quasi-quotes, splces, etc, etc, + * etc. + * + *****************************************************************/ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "CharacterCategory.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +// See https://github.com/ghc/ghc/blob/master/compiler/parser/Lexer.x#L1682 +// Note, letter modifiers are prohibited. + +static int u_iswupper (int ch) { + CharacterCategory c = CategoriseCharacter(ch); + return c == ccLu || c == ccLt; +} + +static int u_iswalpha (int ch) { + CharacterCategory c = CategoriseCharacter(ch); + return c == ccLl || c == ccLu || c == ccLt || c == ccLo; +} + +static int u_iswalnum (int ch) { + CharacterCategory c = CategoriseCharacter(ch); + return c == ccLl || c == ccLu || c == ccLt || c == ccLo + || c == ccNd || c == ccNo; +} + +static int u_IsHaskellSymbol(int ch) { + CharacterCategory c = CategoriseCharacter(ch); + return c == ccPc || c == ccPd || c == ccPo + || c == ccSm || c == ccSc || c == ccSk || c == ccSo; +} + +static inline bool IsHaskellLetter(const int ch) { + if (IsASCII(ch)) { + return (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z'); + } else { + return u_iswalpha(ch) != 0; + } +} + +static inline bool IsHaskellAlphaNumeric(const int ch) { + if (IsASCII(ch)) { + return IsAlphaNumeric(ch); + } else { + return u_iswalnum(ch) != 0; + } +} + +static inline bool IsHaskellUpperCase(const int ch) { + if (IsASCII(ch)) { + return ch >= 'A' && ch <= 'Z'; + } else { + return u_iswupper(ch) != 0; + } +} + +static inline bool IsAnHaskellOperatorChar(const int ch) { + if (IsASCII(ch)) { + return + ( ch == '!' || ch == '#' || ch == '$' || ch == '%' + || ch == '&' || ch == '*' || ch == '+' || ch == '-' + || ch == '.' || ch == '/' || ch == ':' || ch == '<' + || ch == '=' || ch == '>' || ch == '?' || ch == '@' + || ch == '^' || ch == '|' || ch == '~' || ch == '\\'); + } else { + return u_IsHaskellSymbol(ch) != 0; + } +} + +static inline bool IsAHaskellWordStart(const int ch) { + return IsHaskellLetter(ch) || ch == '_'; +} + +static inline bool IsAHaskellWordChar(const int ch) { + return ( IsHaskellAlphaNumeric(ch) + || ch == '_' + || ch == '\''); +} + +static inline bool IsCommentBlockStyle(int style) { + return (style >= SCE_HA_COMMENTBLOCK && style <= SCE_HA_COMMENTBLOCK3); +} + +static inline bool IsCommentStyle(int style) { + return (style >= SCE_HA_COMMENTLINE && style <= SCE_HA_COMMENTBLOCK3) + || ( style == SCE_HA_LITERATE_COMMENT + || style == SCE_HA_LITERATE_CODEDELIM); +} + +// styles which do not belong to Haskell, but to external tools +static inline bool IsExternalStyle(int style) { + return ( style == SCE_HA_PREPROCESSOR + || style == SCE_HA_LITERATE_COMMENT + || style == SCE_HA_LITERATE_CODEDELIM); +} + +static inline int CommentBlockStyleFromNestLevel(const unsigned int nestLevel) { + return SCE_HA_COMMENTBLOCK + (nestLevel % 3); +} + +// Mangled version of lexlib/Accessor.cxx IndentAmount. +// Modified to treat comment blocks as whitespace +// plus special case for commentline/preprocessor. +static int HaskellIndentAmount(Accessor &styler, const Sci_Position line) { + + // Determines the indentation level of the current line + // Comment blocks are treated as whitespace + + Sci_Position pos = styler.LineStart(line); + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + + char ch = styler[pos]; + int style = styler.StyleAt(pos); + + int indent = 0; + bool inPrevPrefix = line > 0; + + Sci_Position posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0; + + while (( ch == ' ' || ch == '\t' + || IsCommentBlockStyle(style) + || style == SCE_HA_LITERATE_CODEDELIM) + && (pos < eol_pos)) { + if (inPrevPrefix) { + char chPrev = styler[posPrev++]; + if (chPrev != ' ' && chPrev != '\t') { + inPrevPrefix = false; + } + } + if (ch == '\t') { + indent = (indent / 8 + 1) * 8; + } else { // Space or comment block + indent++; + } + pos++; + ch = styler[pos]; + style = styler.StyleAt(pos); + } + + indent += SC_FOLDLEVELBASE; + // if completely empty line or the start of a comment or preprocessor... + if ( styler.LineStart(line) == styler.Length() + || ch == ' ' + || ch == '\t' + || ch == '\n' + || ch == '\r' + || IsCommentStyle(style) + || style == SCE_HA_PREPROCESSOR) + return indent | SC_FOLDLEVELWHITEFLAG; + else + return indent; +} + +struct OptionsHaskell { + bool magicHash; + bool allowQuotes; + bool implicitParams; + bool highlightSafe; + bool cpp; + bool stylingWithinPreprocessor; + bool fold; + bool foldComment; + bool foldCompact; + bool foldImports; + OptionsHaskell() { + magicHash = true; // Widespread use, enabled by default. + allowQuotes = true; // Widespread use, enabled by default. + implicitParams = false; // Fell out of favor, seldom used, disabled. + highlightSafe = true; // Moderately used, doesn't hurt to enable. + cpp = true; // Widespread use, enabled by default; + stylingWithinPreprocessor = false; + fold = false; + foldComment = false; + foldCompact = false; + foldImports = false; + } +}; + +static const char * const haskellWordListDesc[] = { + "Keywords", + "FFI", + "Reserved operators", + 0 +}; + +struct OptionSetHaskell : public OptionSet { + OptionSetHaskell() { + DefineProperty("lexer.haskell.allow.hash", &OptionsHaskell::magicHash, + "Set to 0 to disallow the '#' character at the end of identifiers and " + "literals with the haskell lexer " + "(GHC -XMagicHash extension)"); + + DefineProperty("lexer.haskell.allow.quotes", &OptionsHaskell::allowQuotes, + "Set to 0 to disable highlighting of Template Haskell name quotations " + "and promoted constructors " + "(GHC -XTemplateHaskell and -XDataKinds extensions)"); + + DefineProperty("lexer.haskell.allow.questionmark", &OptionsHaskell::implicitParams, + "Set to 1 to allow the '?' character at the start of identifiers " + "with the haskell lexer " + "(GHC & Hugs -XImplicitParams extension)"); + + DefineProperty("lexer.haskell.import.safe", &OptionsHaskell::highlightSafe, + "Set to 0 to disallow \"safe\" keyword in imports " + "(GHC -XSafe, -XTrustworthy, -XUnsafe extensions)"); + + DefineProperty("lexer.haskell.cpp", &OptionsHaskell::cpp, + "Set to 0 to disable C-preprocessor highlighting " + "(-XCPP extension)"); + + DefineProperty("styling.within.preprocessor", &OptionsHaskell::stylingWithinPreprocessor, + "For Haskell code, determines whether all preprocessor code is styled in the " + "preprocessor style (0, the default) or only from the initial # to the end " + "of the command word(1)." + ); + + DefineProperty("fold", &OptionsHaskell::fold); + + DefineProperty("fold.comment", &OptionsHaskell::foldComment); + + DefineProperty("fold.compact", &OptionsHaskell::foldCompact); + + DefineProperty("fold.haskell.imports", &OptionsHaskell::foldImports, + "Set to 1 to enable folding of import declarations"); + + DefineWordListSets(haskellWordListDesc); + } +}; + +class LexerHaskell : public DefaultLexer { + bool literate; + Sci_Position firstImportLine; + int firstImportIndent; + WordList keywords; + WordList ffi; + WordList reserved_operators; + OptionsHaskell options; + OptionSetHaskell osHaskell; + + enum HashCount { + oneHash + ,twoHashes + ,unlimitedHashes + }; + + enum KeywordMode { + HA_MODE_DEFAULT = 0 + ,HA_MODE_IMPORT1 = 1 // after "import", before "qualified" or "safe" or package name or module name. + ,HA_MODE_IMPORT2 = 2 // after module name, before "as" or "hiding". + ,HA_MODE_IMPORT3 = 3 // after "as", before "hiding" + ,HA_MODE_MODULE = 4 // after "module", before module name. + ,HA_MODE_FFI = 5 // after "foreign", before FFI keywords + ,HA_MODE_TYPE = 6 // after "type" or "data", before "family" + }; + + enum LiterateMode { + LITERATE_BIRD = 0 // if '>' is the first character on the line, + // color '>' as a codedelim and the rest of + // the line as code. + // else if "\begin{code}" is the only word on the + // line except whitespace, switch to LITERATE_BLOCK + // otherwise color the line as a literate comment. + ,LITERATE_BLOCK = 1 // if the string "\end{code}" is encountered at column + // 0 ignoring all later characters, color the line + // as a codedelim and switch to LITERATE_BIRD + // otherwise color the line as code. + }; + + struct HaskellLineInfo { + unsigned int nestLevel; // 22 bits ought to be enough for anybody + unsigned int nonexternalStyle; // 5 bits, widen if number of styles goes + // beyond 31. + bool pragma; + LiterateMode lmode; + KeywordMode mode; + + HaskellLineInfo(int state) : + nestLevel (state >> 10) + , nonexternalStyle ((state >> 5) & 0x1F) + , pragma ((state >> 4) & 0x1) + , lmode (static_cast((state >> 3) & 0x1)) + , mode (static_cast(state & 0x7)) + {} + + int ToLineState() { + return + (nestLevel << 10) + | (nonexternalStyle << 5) + | (pragma << 4) + | (lmode << 3) + | mode; + } + }; + + inline void skipMagicHash(StyleContext &sc, const HashCount hashes) const { + if (options.magicHash && sc.ch == '#') { + sc.Forward(); + if (hashes == twoHashes && sc.ch == '#') { + sc.Forward(); + } else if (hashes == unlimitedHashes) { + while (sc.ch == '#') { + sc.Forward(); + } + } + } + } + + bool LineContainsImport(const Sci_Position line, Accessor &styler) const { + if (options.foldImports) { + Sci_Position currentPos = styler.LineStart(line); + int style = styler.StyleAt(currentPos); + + Sci_Position eol_pos = styler.LineStart(line + 1) - 1; + + while (currentPos < eol_pos) { + int ch = styler[currentPos]; + style = styler.StyleAt(currentPos); + + if (ch == ' ' || ch == '\t' + || IsCommentBlockStyle(style) + || style == SCE_HA_LITERATE_CODEDELIM) { + currentPos++; + } else { + break; + } + } + + return (style == SCE_HA_KEYWORD + && styler.Match(currentPos, "import")); + } else { + return false; + } + } + + inline int IndentAmountWithOffset(Accessor &styler, const Sci_Position line) const { + const int indent = HaskellIndentAmount(styler, line); + const int indentLevel = indent & SC_FOLDLEVELNUMBERMASK; + return indentLevel <= ((firstImportIndent - 1) + SC_FOLDLEVELBASE) + ? indent + : (indentLevel + firstImportIndent) | (indent & ~SC_FOLDLEVELNUMBERMASK); + } + + inline int IndentLevelRemoveIndentOffset(const int indentLevel) const { + return indentLevel <= ((firstImportIndent - 1) + SC_FOLDLEVELBASE) + ? indentLevel + : indentLevel - firstImportIndent; + } + +public: + LexerHaskell(bool literate_) + : DefaultLexer(literate_ ? "literatehaskell" : "haskell", literate_ ? SCLEX_LITERATEHASKELL : SCLEX_HASKELL) + , literate(literate_) + , firstImportLine(-1) + , firstImportIndent(0) + {} + virtual ~LexerHaskell() {} + + void SCI_METHOD Release() override { + delete this; + } + + int SCI_METHOD Version() const override { + return lvRelease5; + } + + const char * SCI_METHOD PropertyNames() override { + return osHaskell.PropertyNames(); + } + + int SCI_METHOD PropertyType(const char *name) override { + return osHaskell.PropertyType(name); + } + + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osHaskell.DescribeProperty(name); + } + + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + + const char * SCI_METHOD PropertyGet(const char *key) override { + return osHaskell.PropertyGet(key); + } + + const char * SCI_METHOD DescribeWordListSets() override { + return osHaskell.DescribeWordListSets(); + } + + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + + static ILexer5 *LexerFactoryHaskell() { + return new LexerHaskell(false); + } + + static ILexer5 *LexerFactoryLiterateHaskell() { + return new LexerHaskell(true); + } +}; + +Sci_Position SCI_METHOD LexerHaskell::PropertySet(const char *key, const char *val) { + if (osHaskell.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerHaskell::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &ffi; + break; + case 2: + wordListN = &reserved_operators; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerHaskell::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle + ,IDocument *pAccess) { + LexAccessor styler(pAccess); + + Sci_Position lineCurrent = styler.GetLine(startPos); + + HaskellLineInfo hs = HaskellLineInfo(lineCurrent ? styler.GetLineState(lineCurrent-1) : 0); + + // Do not leak onto next line + if (initStyle == SCE_HA_STRINGEOL) + initStyle = SCE_HA_DEFAULT; + else if (initStyle == SCE_HA_LITERATE_CODEDELIM) + initStyle = hs.nonexternalStyle; + + StyleContext sc(startPos, length, initStyle, styler); + + int base = 10; + bool dot = false; + + bool inDashes = false; + bool alreadyInTheMiddleOfOperator = false; + + assert(!(IsCommentBlockStyle(initStyle) && hs.nestLevel == 0)); + + while (sc.More()) { + // Check for state end + + if (!IsExternalStyle(sc.state)) { + hs.nonexternalStyle = sc.state; + } + + // For lexer to work, states should unconditionally forward at least one + // character. + // If they don't, they should still check if they are at line end and + // forward if so. + // If a state forwards more than one character, it should check every time + // that it is not a line end and cease forwarding otherwise. + if (sc.atLineEnd) { + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, hs.ToLineState()); + lineCurrent++; + } + + // Handle line continuation generically. + if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r') + && ( sc.state == SCE_HA_STRING + || sc.state == SCE_HA_PREPROCESSOR)) { + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, hs.ToLineState()); + lineCurrent++; + + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + sc.Forward(); + + continue; + } + + if (sc.atLineStart) { + + if (sc.state == SCE_HA_STRING || sc.state == SCE_HA_CHARACTER) { + // Prevent SCE_HA_STRINGEOL from leaking back to previous line + sc.SetState(sc.state); + } + + if (literate && hs.lmode == LITERATE_BIRD) { + if (!IsExternalStyle(sc.state)) { + sc.SetState(SCE_HA_LITERATE_COMMENT); + } + } + } + + // External + // Literate + if ( literate && hs.lmode == LITERATE_BIRD && sc.atLineStart + && sc.ch == '>') { + sc.SetState(SCE_HA_LITERATE_CODEDELIM); + sc.ForwardSetState(hs.nonexternalStyle); + } + else if (literate && hs.lmode == LITERATE_BIRD && sc.atLineStart + && ( sc.ch == ' ' || sc.ch == '\t' + || sc.Match("\\begin{code}"))) { + sc.SetState(sc.state); + + while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()) + sc.Forward(); + + if (sc.Match("\\begin{code}")) { + sc.Forward(static_cast(strlen("\\begin{code}"))); + + bool correct = true; + + while (!sc.atLineEnd && sc.More()) { + if (sc.ch != ' ' && sc.ch != '\t') { + correct = false; + } + sc.Forward(); + } + + if (correct) { + sc.ChangeState(SCE_HA_LITERATE_CODEDELIM); // color the line end + hs.lmode = LITERATE_BLOCK; + } + } + } + else if (literate && hs.lmode == LITERATE_BLOCK && sc.atLineStart + && sc.Match("\\end{code}")) { + sc.SetState(SCE_HA_LITERATE_CODEDELIM); + + sc.Forward(static_cast(strlen("\\end{code}"))); + + while (!sc.atLineEnd && sc.More()) { + sc.Forward(); + } + + sc.SetState(SCE_HA_LITERATE_COMMENT); + hs.lmode = LITERATE_BIRD; + } + // Preprocessor + else if (sc.atLineStart && sc.ch == '#' && options.cpp + && (!options.stylingWithinPreprocessor || sc.state == SCE_HA_DEFAULT)) { + sc.SetState(SCE_HA_PREPROCESSOR); + sc.Forward(); + } + // Literate + else if (sc.state == SCE_HA_LITERATE_COMMENT) { + sc.Forward(); + } + else if (sc.state == SCE_HA_LITERATE_CODEDELIM) { + sc.ForwardSetState(hs.nonexternalStyle); + } + // Preprocessor + else if (sc.state == SCE_HA_PREPROCESSOR) { + if (sc.atLineEnd) { + sc.SetState(options.stylingWithinPreprocessor + ? SCE_HA_DEFAULT + : hs.nonexternalStyle); + sc.Forward(); // prevent double counting a line + } else if (options.stylingWithinPreprocessor && !IsHaskellLetter(sc.ch)) { + sc.SetState(SCE_HA_DEFAULT); + } else { + sc.Forward(); + } + } + // Haskell + // Operator + else if (sc.state == SCE_HA_OPERATOR) { + int style = SCE_HA_OPERATOR; + + if ( sc.ch == ':' + && !alreadyInTheMiddleOfOperator + // except "::" + && !( sc.chNext == ':' + && !IsAnHaskellOperatorChar(sc.GetRelative(2)))) { + style = SCE_HA_CAPITAL; + } + + alreadyInTheMiddleOfOperator = false; + + while (IsAnHaskellOperatorChar(sc.ch)) + sc.Forward(); + + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (reserved_operators.InList(s)) + style = SCE_HA_RESERVED_OPERATOR; + + sc.ChangeState(style); + sc.SetState(SCE_HA_DEFAULT); + } + // String + else if (sc.state == SCE_HA_STRING) { + if (sc.atLineEnd) { + sc.ChangeState(SCE_HA_STRINGEOL); + sc.ForwardSetState(SCE_HA_DEFAULT); + } else if (sc.ch == '\"') { + sc.Forward(); + skipMagicHash(sc, oneHash); + sc.SetState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(2); + } else { + sc.Forward(); + } + } + // Char + else if (sc.state == SCE_HA_CHARACTER) { + if (sc.atLineEnd) { + sc.ChangeState(SCE_HA_STRINGEOL); + sc.ForwardSetState(SCE_HA_DEFAULT); + } else if (sc.ch == '\'') { + sc.Forward(); + skipMagicHash(sc, oneHash); + sc.SetState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(2); + } else { + sc.Forward(); + } + } + // Number + else if (sc.state == SCE_HA_NUMBER) { + if (sc.atLineEnd) { + sc.SetState(SCE_HA_DEFAULT); + sc.Forward(); // prevent double counting a line + } else if (IsADigit(sc.ch, base)) { + sc.Forward(); + } else if (sc.ch=='.' && dot && IsADigit(sc.chNext, base)) { + sc.Forward(2); + dot = false; + } else if ((base == 10) && + (sc.ch == 'e' || sc.ch == 'E') && + (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) { + sc.Forward(); + if (sc.ch == '+' || sc.ch == '-') + sc.Forward(); + } else { + skipMagicHash(sc, twoHashes); + sc.SetState(SCE_HA_DEFAULT); + } + } + // Keyword or Identifier + else if (sc.state == SCE_HA_IDENTIFIER) { + int style = IsHaskellUpperCase(sc.ch) ? SCE_HA_CAPITAL : SCE_HA_IDENTIFIER; + + assert(IsAHaskellWordStart(sc.ch)); + + sc.Forward(); + + while (sc.More()) { + if (IsAHaskellWordChar(sc.ch)) { + sc.Forward(); + } else if (sc.ch == '.' && style == SCE_HA_CAPITAL) { + if (IsHaskellUpperCase(sc.chNext)) { + sc.Forward(); + style = SCE_HA_CAPITAL; + } else if (IsAHaskellWordStart(sc.chNext)) { + sc.Forward(); + style = SCE_HA_IDENTIFIER; + } else if (IsAnHaskellOperatorChar(sc.chNext)) { + sc.Forward(); + style = sc.ch == ':' ? SCE_HA_CAPITAL : SCE_HA_OPERATOR; + while (IsAnHaskellOperatorChar(sc.ch)) + sc.Forward(); + break; + } else { + break; + } + } else { + break; + } + } + + skipMagicHash(sc, unlimitedHashes); + + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + KeywordMode new_mode = HA_MODE_DEFAULT; + + if (keywords.InList(s)) { + style = SCE_HA_KEYWORD; + } else if (style == SCE_HA_CAPITAL) { + if (hs.mode == HA_MODE_IMPORT1 || hs.mode == HA_MODE_IMPORT3) { + style = SCE_HA_MODULE; + new_mode = HA_MODE_IMPORT2; + } else if (hs.mode == HA_MODE_MODULE) { + style = SCE_HA_MODULE; + } + } else if (hs.mode == HA_MODE_IMPORT1 && + strcmp(s,"qualified") == 0) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_IMPORT1; + } else if (options.highlightSafe && + hs.mode == HA_MODE_IMPORT1 && + strcmp(s,"safe") == 0) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_IMPORT1; + } else if (hs.mode == HA_MODE_IMPORT2) { + if (strcmp(s,"as") == 0) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_IMPORT3; + } else if (strcmp(s,"hiding") == 0) { + style = SCE_HA_KEYWORD; + } + } else if (hs.mode == HA_MODE_TYPE) { + if (strcmp(s,"family") == 0) + style = SCE_HA_KEYWORD; + } + + if (hs.mode == HA_MODE_FFI) { + if (ffi.InList(s)) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_FFI; + } + } + + sc.ChangeState(style); + sc.SetState(SCE_HA_DEFAULT); + + if (strcmp(s,"import") == 0 && hs.mode != HA_MODE_FFI) + new_mode = HA_MODE_IMPORT1; + else if (strcmp(s,"module") == 0) + new_mode = HA_MODE_MODULE; + else if (strcmp(s,"foreign") == 0) + new_mode = HA_MODE_FFI; + else if (strcmp(s,"type") == 0 + || strcmp(s,"data") == 0) + new_mode = HA_MODE_TYPE; + + hs.mode = new_mode; + } + + // Comments + // Oneliner + else if (sc.state == SCE_HA_COMMENTLINE) { + if (sc.atLineEnd) { + sc.SetState(hs.pragma ? SCE_HA_PRAGMA : SCE_HA_DEFAULT); + sc.Forward(); // prevent double counting a line + } else if (inDashes && sc.ch != '-' && !hs.pragma) { + inDashes = false; + if (IsAnHaskellOperatorChar(sc.ch)) { + alreadyInTheMiddleOfOperator = true; + sc.ChangeState(SCE_HA_OPERATOR); + } + } else { + sc.Forward(); + } + } + // Nested + else if (IsCommentBlockStyle(sc.state)) { + if (sc.Match('{','-')) { + sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel)); + sc.Forward(2); + hs.nestLevel++; + } else if (sc.Match('-','}')) { + sc.Forward(2); + assert(hs.nestLevel > 0); + if (hs.nestLevel > 0) + hs.nestLevel--; + sc.SetState( + hs.nestLevel == 0 + ? (hs.pragma ? SCE_HA_PRAGMA : SCE_HA_DEFAULT) + : CommentBlockStyleFromNestLevel(hs.nestLevel - 1)); + } else { + sc.Forward(); + } + } + // Pragma + else if (sc.state == SCE_HA_PRAGMA) { + if (sc.Match("#-}")) { + hs.pragma = false; + sc.Forward(3); + sc.SetState(SCE_HA_DEFAULT); + } else if (sc.Match('-','-')) { + sc.SetState(SCE_HA_COMMENTLINE); + sc.Forward(2); + inDashes = false; + } else if (sc.Match('{','-')) { + sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel)); + sc.Forward(2); + hs.nestLevel = 1; + } else { + sc.Forward(); + } + } + // New state? + else if (sc.state == SCE_HA_DEFAULT) { + // Digit + if (IsADigit(sc.ch)) { + hs.mode = HA_MODE_DEFAULT; + + sc.SetState(SCE_HA_NUMBER); + if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { + // Match anything starting with "0x" or "0X", too + sc.Forward(2); + base = 16; + dot = false; + } else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) { + // Match anything starting with "0o" or "0O", too + sc.Forward(2); + base = 8; + dot = false; + } else { + sc.Forward(); + base = 10; + dot = true; + } + } + // Pragma + else if (sc.Match("{-#")) { + hs.pragma = true; + sc.SetState(SCE_HA_PRAGMA); + sc.Forward(3); + } + // Comment line + else if (sc.Match('-','-')) { + sc.SetState(SCE_HA_COMMENTLINE); + sc.Forward(2); + inDashes = true; + } + // Comment block + else if (sc.Match('{','-')) { + sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel)); + sc.Forward(2); + hs.nestLevel = 1; + } + // String + else if (sc.ch == '\"') { + sc.SetState(SCE_HA_STRING); + sc.Forward(); + } + // Character or quoted name or promoted term + else if (sc.ch == '\'') { + hs.mode = HA_MODE_DEFAULT; + + sc.SetState(SCE_HA_CHARACTER); + sc.Forward(); + + if (options.allowQuotes) { + // Quoted type ''T + if (sc.ch=='\'' && IsAHaskellWordStart(sc.chNext)) { + sc.Forward(); + sc.ChangeState(SCE_HA_IDENTIFIER); + } else if (sc.chNext != '\'') { + // Quoted name 'n or promoted constructor 'N + if (IsAHaskellWordStart(sc.ch)) { + sc.ChangeState(SCE_HA_IDENTIFIER); + // Promoted constructor operator ':~> + } else if (sc.ch == ':') { + alreadyInTheMiddleOfOperator = false; + sc.ChangeState(SCE_HA_OPERATOR); + // Promoted list or tuple '[T] + } else if (sc.ch == '[' || sc.ch== '(') { + sc.ChangeState(SCE_HA_OPERATOR); + sc.ForwardSetState(SCE_HA_DEFAULT); + } + } + } + } + // Operator starting with '?' or an implicit parameter + else if (sc.ch == '?') { + hs.mode = HA_MODE_DEFAULT; + + alreadyInTheMiddleOfOperator = false; + sc.SetState(SCE_HA_OPERATOR); + + if ( options.implicitParams + && IsAHaskellWordStart(sc.chNext) + && !IsHaskellUpperCase(sc.chNext)) { + sc.Forward(); + sc.ChangeState(SCE_HA_IDENTIFIER); + } + } + // Operator + else if (IsAnHaskellOperatorChar(sc.ch)) { + hs.mode = HA_MODE_DEFAULT; + + sc.SetState(SCE_HA_OPERATOR); + } + // Braces and punctuation + else if (sc.ch == ',' || sc.ch == ';' + || sc.ch == '(' || sc.ch == ')' + || sc.ch == '[' || sc.ch == ']' + || sc.ch == '{' || sc.ch == '}') { + sc.SetState(SCE_HA_OPERATOR); + sc.ForwardSetState(SCE_HA_DEFAULT); + } + // Keyword or Identifier + else if (IsAHaskellWordStart(sc.ch)) { + sc.SetState(SCE_HA_IDENTIFIER); + // Something we don't care about + } else { + sc.Forward(); + } + } + // This branch should never be reached. + else { + assert(false); + sc.Forward(); + } + } + sc.Complete(); +} + +void SCI_METHOD LexerHaskell::Fold(Sci_PositionU startPos, Sci_Position length, int // initStyle + ,IDocument *pAccess) { + if (!options.fold) + return; + + Accessor styler(pAccess, NULL); + + Sci_Position lineCurrent = styler.GetLine(startPos); + + if (lineCurrent <= firstImportLine) { + firstImportLine = -1; // readjust first import position + firstImportIndent = 0; + } + + const Sci_Position maxPos = startPos + length; + const Sci_Position maxLines = + maxPos == styler.Length() + ? styler.GetLine(maxPos) + : styler.GetLine(maxPos - 1); // Requested last line + const Sci_Position docLines = styler.GetLine(styler.Length()); // Available last line + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + bool importHere = LineContainsImport(lineCurrent, styler); + int indentCurrent = IndentAmountWithOffset(styler, lineCurrent); + + while (lineCurrent > 0) { + lineCurrent--; + importHere = LineContainsImport(lineCurrent, styler); + indentCurrent = IndentAmountWithOffset(styler, lineCurrent); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) + break; + } + + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + if (importHere) { + indentCurrentLevel = IndentLevelRemoveIndentOffset(indentCurrentLevel); + if (firstImportLine == -1) { + firstImportLine = lineCurrent; + firstImportIndent = (1 + indentCurrentLevel) - SC_FOLDLEVELBASE; + } + if (firstImportLine != lineCurrent) { + indentCurrentLevel++; + } + } + + indentCurrent = indentCurrentLevel | (indentCurrent & ~SC_FOLDLEVELNUMBERMASK); + + // Process all characters to end of requested range + //that hangs over the end of the range. Cap processing in all cases + // to end of document. + while (lineCurrent <= docLines && lineCurrent <= maxLines) { + + // Gather info + Sci_Position lineNext = lineCurrent + 1; + importHere = false; + int indentNext = indentCurrent; + + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + importHere = LineContainsImport(lineNext, styler); + indentNext = IndentAmountWithOffset(styler, lineNext); + } + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. + + while (lineNext < docLines && (indentNext & SC_FOLDLEVELWHITEFLAG)) { + lineNext++; + importHere = LineContainsImport(lineNext, styler); + indentNext = IndentAmountWithOffset(styler, lineNext); + } + + int indentNextLevel = indentNext & SC_FOLDLEVELNUMBERMASK; + + if (importHere) { + indentNextLevel = IndentLevelRemoveIndentOffset(indentNextLevel); + if (firstImportLine == -1) { + firstImportLine = lineNext; + firstImportIndent = (1 + indentNextLevel) - SC_FOLDLEVELBASE; + } + if (firstImportLine != lineNext) { + indentNextLevel++; + } + } + + indentNext = indentNextLevel | (indentNext & ~SC_FOLDLEVELNUMBERMASK); + + const int levelBeforeComments = Maximum(indentCurrentLevel,indentNextLevel); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + Sci_Position skipLine = lineNext; + int skipLevel = indentNextLevel; + + while (--skipLine > lineCurrent) { + int skipLineIndent = IndentAmountWithOffset(styler, skipLine); + + if (options.foldCompact) { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel) { + skipLevel = levelBeforeComments; + } + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } else { + if ( (skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel + && !(skipLineIndent & SC_FOLDLEVELWHITEFLAG)) { + skipLevel = levelBeforeComments; + } + + styler.SetLevel(skipLine, skipLevel); + } + } + + int lev = indentCurrent; + + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, options.foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG); + + indentCurrent = indentNext; + indentCurrentLevel = indentNextLevel; + lineCurrent = lineNext; + } + + // NOTE: Cannot set level of last line here because indentCurrent doesn't have + // header flag set; the loop above is crafted to take care of this case! + //styler.SetLevel(lineCurrent, indentCurrent); +} + +extern const LexerModule lmHaskell(SCLEX_HASKELL, LexerHaskell::LexerFactoryHaskell, "haskell", haskellWordListDesc); +extern const LexerModule lmLiterateHaskell(SCLEX_LITERATEHASKELL, LexerHaskell::LexerFactoryLiterateHaskell, "literatehaskell", haskellWordListDesc); diff --git a/src/lexilla/lexers/LexHex.cxx b/src/lexilla/lexers/LexHex.cxx new file mode 100644 index 000000000..e3782a19a --- /dev/null +++ b/src/lexilla/lexers/LexHex.cxx @@ -0,0 +1,1048 @@ +// Scintilla source code edit control +/** @file LexHex.cxx + ** Lexers for Motorola S-Record, Intel HEX and Tektronix extended HEX. + ** + ** Written by Markus Heidelberg + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +/* + * Motorola S-Record + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 ('S') SCE_HEX_RECSTART + * +----------+ + * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | address | 4/6/8 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, SCE_HEX_RECCOUNT, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | data | 0..504/502/500 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, (SCE_HEX_DATA_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * + * + * Intel HEX + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 (':') SCE_HEX_RECSTART + * +----------+ + * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | address | 4 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | type | 2 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | data | 0..510 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, SCE_HEX_EXTENDEDADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_DATA_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * + * + * Folding: + * + * Data records (type 0x00), which follow an extended address record (type + * 0x02 or 0x04), can be folded. The extended address record is the fold + * point at fold level 0, the corresponding data records are set to level 1. + * + * Any record, which is not a data record, sets the fold level back to 0. + * Any line, which is not a record (blank lines and lines starting with a + * character other than ':'), leaves the fold level unchanged. + * + * + * Tektronix extended HEX + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 ('%') SCE_HEX_RECSTART + * +----------+ + * | length | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * | address | 9 SCE_HEX_DATAADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | data | 0..241 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN + * +----------+ + * + * + * General notes for all lexers + * =============================== + * + * - Depending on where the helper functions are invoked, some of them have to + * read beyond the current position. In case of malformed data (record too + * short), it has to be ensured that this either does not have bad influence + * or will be captured deliberately. + * + * - States in parentheses in the upper format descriptions indicate that they + * should not appear in a valid hex file. + * + * - State SCE_HEX_GARBAGE means garbage data after the intended end of the + * record, the line is too long then. This state is used in all lexers. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +// prototypes for general helper functions +static inline bool IsNewline(const int ch); +static int GetHexaNibble(char hd); +static int GetHexaChar(char hd1, char hd2); +static int GetHexaChar(Sci_PositionU pos, Accessor &styler); +static bool ForwardWithinLine(StyleContext &sc, Sci_Position nb = 1); +static bool PosInSameRecord(Sci_PositionU pos1, Sci_PositionU pos2, Accessor &styler); +static Sci_Position CountByteCount(Sci_PositionU startPos, Sci_Position uncountedDigits, Accessor &styler); +static int CalcChecksum(Sci_PositionU startPos, Sci_Position cnt, bool twosCompl, Accessor &styler); + +// prototypes for file format specific helper functions +static Sci_PositionU GetSrecRecStartPosition(Sci_PositionU pos, Accessor &styler); +static int GetSrecByteCount(Sci_PositionU recStartPos, Accessor &styler); +static Sci_Position CountSrecByteCount(Sci_PositionU recStartPos, Accessor &styler); +static int GetSrecAddressFieldSize(Sci_PositionU recStartPos, Accessor &styler); +static int GetSrecAddressFieldType(Sci_PositionU recStartPos, Accessor &styler); +static int GetSrecDataFieldType(Sci_PositionU recStartPos, Accessor &styler); +static Sci_Position GetSrecRequiredDataFieldSize(Sci_PositionU recStartPos, Accessor &styler); +static int GetSrecChecksum(Sci_PositionU recStartPos, Accessor &styler); +static int CalcSrecChecksum(Sci_PositionU recStartPos, Accessor &styler); + +static Sci_PositionU GetIHexRecStartPosition(Sci_PositionU pos, Accessor &styler); +static int GetIHexByteCount(Sci_PositionU recStartPos, Accessor &styler); +static Sci_Position CountIHexByteCount(Sci_PositionU recStartPos, Accessor &styler); +static int GetIHexAddressFieldType(Sci_PositionU recStartPos, Accessor &styler); +static int GetIHexDataFieldType(Sci_PositionU recStartPos, Accessor &styler); +static int GetIHexRequiredDataFieldSize(Sci_PositionU recStartPos, Accessor &styler); +static int GetIHexChecksum(Sci_PositionU recStartPos, Accessor &styler); +static int CalcIHexChecksum(Sci_PositionU recStartPos, Accessor &styler); + +static int GetTEHexDigitCount(Sci_PositionU recStartPos, Accessor &styler); +static Sci_Position CountTEHexDigitCount(Sci_PositionU recStartPos, Accessor &styler); +static int GetTEHexAddressFieldType(Sci_PositionU recStartPos, Accessor &styler); +static int GetTEHexChecksum(Sci_PositionU recStartPos, Accessor &styler); +static int CalcTEHexChecksum(Sci_PositionU recStartPos, Accessor &styler); + +static inline bool IsNewline(const int ch) +{ + return (ch == '\n' || ch == '\r'); +} + +static int GetHexaNibble(char hd) +{ + int hexValue = 0; + + if (hd >= '0' && hd <= '9') { + hexValue += hd - '0'; + } else if (hd >= 'A' && hd <= 'F') { + hexValue += hd - 'A' + 10; + } else if (hd >= 'a' && hd <= 'f') { + hexValue += hd - 'a' + 10; + } else { + return -1; + } + + return hexValue; +} + +static int GetHexaChar(char hd1, char hd2) +{ + int hexValue = 0; + + if (hd1 >= '0' && hd1 <= '9') { + hexValue += 16 * (hd1 - '0'); + } else if (hd1 >= 'A' && hd1 <= 'F') { + hexValue += 16 * (hd1 - 'A' + 10); + } else if (hd1 >= 'a' && hd1 <= 'f') { + hexValue += 16 * (hd1 - 'a' + 10); + } else { + return -1; + } + + if (hd2 >= '0' && hd2 <= '9') { + hexValue += hd2 - '0'; + } else if (hd2 >= 'A' && hd2 <= 'F') { + hexValue += hd2 - 'A' + 10; + } else if (hd2 >= 'a' && hd2 <= 'f') { + hexValue += hd2 - 'a' + 10; + } else { + return -1; + } + + return hexValue; +} + +static int GetHexaChar(Sci_PositionU pos, Accessor &styler) +{ + char highNibble, lowNibble; + + highNibble = styler.SafeGetCharAt(pos); + lowNibble = styler.SafeGetCharAt(pos + 1); + + return GetHexaChar(highNibble, lowNibble); +} + +// Forward characters, but abort (and return false) if hitting the line +// end. Return true if forwarding within the line was possible. +// Avoids influence on highlighting of the subsequent line if the current line +// is malformed (too short). +static bool ForwardWithinLine(StyleContext &sc, Sci_Position nb) +{ + for (Sci_Position i = 0; i < nb; i++) { + if (sc.atLineEnd) { + // line is too short + sc.SetState(SCE_HEX_DEFAULT); + sc.Forward(); + return false; + } else { + sc.Forward(); + } + } + + return true; +} + +// Checks whether the given positions are in the same record. +static bool PosInSameRecord(Sci_PositionU pos1, Sci_PositionU pos2, Accessor &styler) +{ + return styler.GetLine(pos1) == styler.GetLine(pos2); +} + +// Count the number of digit pairs from till end of record, ignoring +// digits. +// If the record is too short, a negative count may be returned. +static Sci_Position CountByteCount(Sci_PositionU startPos, Sci_Position uncountedDigits, Accessor &styler) +{ + Sci_Position cnt; + Sci_PositionU pos; + + pos = startPos; + + while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) { + pos++; + } + + // number of digits in this line minus number of digits of uncounted fields + cnt = static_cast(pos - startPos) - uncountedDigits; + + // Prepare round up if odd (digit pair incomplete), this way the byte + // count is considered to be valid if the checksum is incomplete. + if (cnt >= 0) { + cnt++; + } + + // digit pairs + cnt /= 2; + + return cnt; +} + +// Calculate the checksum of the record. +// is the position of the first character of the starting digit +// pair, is the number of digit pairs. +static int CalcChecksum(Sci_PositionU startPos, Sci_Position cnt, bool twosCompl, Accessor &styler) +{ + int cs = 0; + + for (Sci_PositionU pos = startPos; pos < startPos + cnt; pos += 2) { + int val = GetHexaChar(pos, styler); + + if (val < 0) { + return val; + } + + // overflow does not matter + cs += val; + } + + if (twosCompl) { + // low byte of two's complement + return -cs & 0xFF; + } else { + // low byte of one's complement + return ~cs & 0xFF; + } +} + +// Get the position of the record "start" field (first character in line) in +// the record around position . +static Sci_PositionU GetSrecRecStartPosition(Sci_PositionU pos, Accessor &styler) +{ + while (styler.SafeGetCharAt(pos) != 'S') { + pos--; + } + + return pos; +} + +// Get the value of the "byte count" field, it counts the number of bytes in +// the subsequent fields ("address", "data" and "checksum" fields). +static int GetSrecByteCount(Sci_PositionU recStartPos, Accessor &styler) +{ + int val; + + val = GetHexaChar(recStartPos + 2, styler); + if (val < 0) { + val = 0; + } + + return val; +} + +// Count the number of digit pairs for the "address", "data" and "checksum" +// fields in this record. Has to be equal to the "byte count" field value. +// If the record is too short, a negative count may be returned. +static Sci_Position CountSrecByteCount(Sci_PositionU recStartPos, Accessor &styler) +{ + return CountByteCount(recStartPos, 4, styler); +} + +// Get the size of the "address" field. +static int GetSrecAddressFieldSize(Sci_PositionU recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + case '1': + case '5': + case '9': + return 2; // 16 bit + + case '2': + case '6': + case '8': + return 3; // 24 bit + + case '3': + case '7': + return 4; // 32 bit + + default: + return 0; + } +} + +// Get the type of the "address" field content. +static int GetSrecAddressFieldType(Sci_PositionU recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + return SCE_HEX_NOADDRESS; + + case '1': + case '2': + case '3': + return SCE_HEX_DATAADDRESS; + + case '5': + case '6': + return SCE_HEX_RECCOUNT; + + case '7': + case '8': + case '9': + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the type of the "data" field content. +static int GetSrecDataFieldType(Sci_PositionU recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + case '1': + case '2': + case '3': + return SCE_HEX_DATA_ODD; + + case '5': + case '6': + case '7': + case '8': + case '9': + return SCE_HEX_DATA_EMPTY; + + default: // handle possible format extension in the future + return SCE_HEX_DATA_UNKNOWN; + } +} + +// Get the required size of the "data" field. Useless for block header and +// ordinary data records (type S0, S1, S2, S3), return the value calculated +// from the "byte count" and "address field" size in this case. +static Sci_Position GetSrecRequiredDataFieldSize(Sci_PositionU recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '5': + case '6': + case '7': + case '8': + case '9': + return 0; + + default: + return GetSrecByteCount(recStartPos, styler) + - GetSrecAddressFieldSize(recStartPos, styler) + - 1; // -1 for checksum field + } +} + +// Get the value of the "checksum" field. +static int GetSrecChecksum(Sci_PositionU recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetSrecByteCount(recStartPos, styler); + + return GetHexaChar(recStartPos + 2 + byteCount * 2, styler); +} + +// Calculate the checksum of the record. +static int CalcSrecChecksum(Sci_PositionU recStartPos, Accessor &styler) +{ + Sci_Position byteCount; + + byteCount = GetSrecByteCount(recStartPos, styler); + + // sum over "byte count", "address" and "data" fields (6..510 digits) + return CalcChecksum(recStartPos + 2, byteCount * 2, false, styler); +} + +// Get the position of the record "start" field (first character in line) in +// the record around position . +static Sci_PositionU GetIHexRecStartPosition(Sci_PositionU pos, Accessor &styler) +{ + while (styler.SafeGetCharAt(pos) != ':') { + pos--; + } + + return pos; +} + +// Get the value of the "byte count" field, it counts the number of bytes in +// the "data" field. +static int GetIHexByteCount(Sci_PositionU recStartPos, Accessor &styler) +{ + int val; + + val = GetHexaChar(recStartPos + 1, styler); + if (val < 0) { + val = 0; + } + + return val; +} + +// Count the number of digit pairs for the "data" field in this record. Has to +// be equal to the "byte count" field value. +// If the record is too short, a negative count may be returned. +static Sci_Position CountIHexByteCount(Sci_PositionU recStartPos, Accessor &styler) +{ + return CountByteCount(recStartPos, 11, styler); +} + +// Get the type of the "address" field content. +static int GetIHexAddressFieldType(Sci_PositionU recStartPos, Accessor &styler) +{ + if (!PosInSameRecord(recStartPos, recStartPos + 7, styler)) { + // malformed (record too short) + // type cannot be determined + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } + + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x00: + return SCE_HEX_DATAADDRESS; + + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + return SCE_HEX_NOADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the type of the "data" field content. +static int GetIHexDataFieldType(Sci_PositionU recStartPos, Accessor &styler) +{ + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x00: + return SCE_HEX_DATA_ODD; + + case 0x01: + return SCE_HEX_DATA_EMPTY; + + case 0x02: + case 0x04: + return SCE_HEX_EXTENDEDADDRESS; + + case 0x03: + case 0x05: + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_DATA_UNKNOWN; + } +} + +// Get the required size of the "data" field. Useless for an ordinary data +// record (type 00), return the "byte count" in this case. +static int GetIHexRequiredDataFieldSize(Sci_PositionU recStartPos, Accessor &styler) +{ + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x01: + return 0; + + case 0x02: + case 0x04: + return 2; + + case 0x03: + case 0x05: + return 4; + + default: + return GetIHexByteCount(recStartPos, styler); + } +} + +// Get the value of the "checksum" field. +static int GetIHexChecksum(Sci_PositionU recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetIHexByteCount(recStartPos, styler); + + return GetHexaChar(recStartPos + 9 + byteCount * 2, styler); +} + +// Calculate the checksum of the record. +static int CalcIHexChecksum(Sci_PositionU recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetIHexByteCount(recStartPos, styler); + + // sum over "byte count", "address", "type" and "data" fields (8..518 digits) + return CalcChecksum(recStartPos + 1, 8 + byteCount * 2, true, styler); +} + + +// Get the value of the "record length" field, it counts the number of digits in +// the record excluding the percent. +static int GetTEHexDigitCount(Sci_PositionU recStartPos, Accessor &styler) +{ + int val = GetHexaChar(recStartPos + 1, styler); + if (val < 0) + val = 0; + + return val; +} + +// Count the number of digits in this record. Has to +// be equal to the "record length" field value. +static Sci_Position CountTEHexDigitCount(Sci_PositionU recStartPos, Accessor &styler) +{ + Sci_PositionU pos; + + pos = recStartPos+1; + + while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) { + pos++; + } + + return static_cast(pos - (recStartPos+1)); +} + +// Get the type of the "address" field content. +static int GetTEHexAddressFieldType(Sci_PositionU recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 3)) { + case '6': + return SCE_HEX_DATAADDRESS; + + case '8': + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the value of the "checksum" field. +static int GetTEHexChecksum(Sci_PositionU recStartPos, Accessor &styler) +{ + return GetHexaChar(recStartPos+4, styler); +} + +// Calculate the checksum of the record (excluding the checksum field). +static int CalcTEHexChecksum(Sci_PositionU recStartPos, Accessor &styler) +{ + Sci_PositionU pos = recStartPos +1; + Sci_PositionU length = GetTEHexDigitCount(recStartPos, styler); + + int cs = GetHexaNibble(styler.SafeGetCharAt(pos++));//length + cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//length + + cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//type + + pos += 2;// jump over CS field + + for (; pos <= recStartPos + length; ++pos) { + int val = GetHexaNibble(styler.SafeGetCharAt(pos)); + + if (val < 0) { + return val; + } + + // overflow does not matter + cs += val; + } + + // low byte + return cs & 0xFF; + +} + +static void ColouriseSrecDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + Sci_PositionU recStartPos; + Sci_Position reqByteCount; + Sci_Position dataFieldSize; + int byteCount, addrFieldSize, addrFieldType, dataFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match('S')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + recStartPos = sc.currentPos - 1; + addrFieldType = GetSrecAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 2; + byteCount = GetSrecByteCount(recStartPos, styler); + reqByteCount = GetSrecAddressFieldSize(recStartPos, styler) + + GetSrecRequiredDataFieldSize(recStartPos, styler) + + 1; // +1 for checksum field + + if (byteCount == CountSrecByteCount(recStartPos, styler) + && byteCount == reqByteCount) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 4; + addrFieldSize = GetSrecAddressFieldSize(recStartPos, styler); + addrFieldType = GetSrecAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, addrFieldSize * 2); + break; + + case SCE_HEX_NOADDRESS: + case SCE_HEX_DATAADDRESS: + case SCE_HEX_RECCOUNT: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = GetSrecRecStartPosition(sc.currentPos, styler); + dataFieldType = GetSrecDataFieldType(recStartPos, styler); + + // Using the required size here if possible has the effect that the + // checksum is highlighted at a fixed position after this field for + // specific record types, independent on the "byte count" value. + dataFieldSize = GetSrecRequiredDataFieldSize(recStartPos, styler); + + sc.SetState(dataFieldType); + + if (dataFieldType == SCE_HEX_DATA_ODD) { + for (int i = 0; i < dataFieldSize * 2; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + } else { + ForwardWithinLine(sc, dataFieldSize * 2); + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_DATA_EMPTY: + case SCE_HEX_DATA_UNKNOWN: + recStartPos = GetSrecRecStartPosition(sc.currentPos, styler); + cs1 = CalcSrecChecksum(recStartPos, styler); + cs2 = GetSrecChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +static void ColouriseIHexDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + Sci_PositionU recStartPos; + int byteCount, addrFieldType, dataFieldSize, dataFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match(':')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + recStartPos = sc.currentPos - 1; + byteCount = GetIHexByteCount(recStartPos, styler); + dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler); + + if (byteCount == CountIHexByteCount(recStartPos, styler) + && byteCount == dataFieldSize) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 3; + addrFieldType = GetIHexAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, 4); + break; + + case SCE_HEX_NOADDRESS: + case SCE_HEX_DATAADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = sc.currentPos - 7; + addrFieldType = GetIHexAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 9; + dataFieldType = GetIHexDataFieldType(recStartPos, styler); + + // Using the required size here if possible has the effect that the + // checksum is highlighted at a fixed position after this field for + // specific record types, independent on the "byte count" value. + dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler); + + sc.SetState(dataFieldType); + + if (dataFieldType == SCE_HEX_DATA_ODD) { + for (int i = 0; i < dataFieldSize * 2; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + } else { + ForwardWithinLine(sc, dataFieldSize * 2); + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_DATA_EMPTY: + case SCE_HEX_EXTENDEDADDRESS: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_DATA_UNKNOWN: + recStartPos = GetIHexRecStartPosition(sc.currentPos, styler); + cs1 = CalcIHexChecksum(recStartPos, styler); + cs2 = GetIHexChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +static void FoldIHexDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) +{ + Sci_PositionU endPos = startPos + length; + + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent - 1); + + Sci_PositionU lineStartNext = styler.LineStart(lineCurrent + 1); + int levelNext = SC_FOLDLEVELBASE; // default if no specific line found + + for (Sci_PositionU i = startPos; i < endPos; i++) { + bool atEOL = i == (lineStartNext - 1); + int style = styler.StyleAt(i); + + // search for specific lines + if (style == SCE_HEX_EXTENDEDADDRESS) { + // extended addres record + levelNext = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + } else if (style == SCE_HEX_DATAADDRESS + || (style == SCE_HEX_DEFAULT + && i == (Sci_PositionU)styler.LineStart(lineCurrent))) { + // data record or no record start code at all + if (levelCurrent & SC_FOLDLEVELHEADERFLAG) { + levelNext = SC_FOLDLEVELBASE + 1; + } else { + // continue level 0 or 1, no fold point + levelNext = levelCurrent; + } + } + + if (atEOL || (i == endPos - 1)) { + styler.SetLevel(lineCurrent, levelNext); + + lineCurrent++; + lineStartNext = styler.LineStart(lineCurrent + 1); + levelCurrent = levelNext; + levelNext = SC_FOLDLEVELBASE; + } + } +} + +static void ColouriseTEHexDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + Sci_PositionU recStartPos; + int digitCount, addrFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match('%')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + + recStartPos = sc.currentPos - 1; + + if (GetTEHexDigitCount(recStartPos, styler) == CountTEHexDigitCount(recStartPos, styler)) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 3; + addrFieldType = GetTEHexAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 4; + cs1 = CalcTEHexChecksum(recStartPos, styler); + cs2 = GetTEHexChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + recStartPos = sc.currentPos - 6; + addrFieldType = GetTEHexAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, 9); + break; + + case SCE_HEX_DATAADDRESS: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = sc.currentPos - 15; + digitCount = GetTEHexDigitCount(recStartPos, styler) - 14; + + sc.SetState(SCE_HEX_DATA_ODD); + + for (int i = 0; i < digitCount; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +extern const LexerModule lmSrec(SCLEX_SREC, ColouriseSrecDoc, "srec", 0, NULL); +extern const LexerModule lmIHex(SCLEX_IHEX, ColouriseIHexDoc, "ihex", FoldIHexDoc, NULL); +extern const LexerModule lmTEHex(SCLEX_TEHEX, ColouriseTEHexDoc, "tehex", 0, NULL); diff --git a/src/lexilla/lexers/LexHollywood.cxx b/src/lexilla/lexers/LexHollywood.cxx new file mode 100644 index 000000000..5faab57fe --- /dev/null +++ b/src/lexilla/lexers/LexHollywood.cxx @@ -0,0 +1,519 @@ +// Scintilla source code edit control +/** @file LexHollywood.cxx + ** Lexer for Hollywood + ** Written by Andreas Falkenhahn, based on the BlitzBasic/PureBasic/Lua lexers + ** Thanks to Nicholai Benalal + ** For more information on Hollywood, see http://www.hollywood-mal.com/ + ** Mail me (andreas airsoftsoftwair de) for any bugs. + ** This code is subject to the same license terms as the rest of the Scintilla project: + ** The License.txt file describes the conditions under which this software may be distributed. + **/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + * 64 - letter + */ +static int character_classification[128] = +{ + 0, // NUL ($0) + 0, // SOH ($1) + 0, // STX ($2) + 0, // ETX ($3) + 0, // EOT ($4) + 0, // ENQ ($5) + 0, // ACK ($6) + 0, // BEL ($7) + 0, // BS ($8) + 1, // HT ($9) + 1, // LF ($A) + 0, // VT ($B) + 0, // FF ($C) + 1, // CR ($D) + 0, // SO ($E) + 0, // SI ($F) + 0, // DLE ($10) + 0, // DC1 ($11) + 0, // DC2 ($12) + 0, // DC3 ($13) + 0, // DC4 ($14) + 0, // NAK ($15) + 0, // SYN ($16) + 0, // ETB ($17) + 0, // CAN ($18) + 0, // EM ($19) + 0, // SUB ($1A) + 0, // ESC ($1B) + 0, // FS ($1C) + 0, // GS ($1D) + 0, // RS ($1E) + 0, // US ($1F) + 1, // space ($20) + 4, // ! ($21) + 0, // " ($22) + 0, // # ($23) + 4, // $ ($24) + 2, // % ($25) + 2, // & ($26) + 2, // ' ($27) + 2, // ( ($28) + 2, // ) ($29) + 2, // * ($2A) + 2, // + ($2B) + 2, // , ($2C) + 2, // - ($2D) + // NB: we treat "." as an identifier although it is also an operator and a decimal digit + // the reason why we treat it as an identifier is to support syntax highlighting for + // plugin commands which always use a "." in their names, e.g. pdf.OpenDocument(); + // we handle the decimal digit case manually below so that 3.1415 and .123 is styled correctly + // the collateral damage of treating "." as an identifier is that "." is never styled + // SCE_HOLLYWOOD_OPERATOR + 4, // . ($2E) + 2, // / ($2F) + 28, // 0 ($30) + 28, // 1 ($31) + 28, // 2 ($32) + 28, // 3 ($33) + 28, // 4 ($34) + 28, // 5 ($35) + 28, // 6 ($36) + 28, // 7 ($37) + 28, // 8 ($38) + 28, // 9 ($39) + 2, // : ($3A) + 2, // ; ($3B) + 2, // < ($3C) + 2, // = ($3D) + 2, // > ($3E) + 2, // ? ($3F) + 0, // @ ($40) + 84, // A ($41) + 84, // B ($42) + 84, // C ($43) + 84, // D ($44) + 84, // E ($45) + 84, // F ($46) + 68, // G ($47) + 68, // H ($48) + 68, // I ($49) + 68, // J ($4A) + 68, // K ($4B) + 68, // L ($4C) + 68, // M ($4D) + 68, // N ($4E) + 68, // O ($4F) + 68, // P ($50) + 68, // Q ($51) + 68, // R ($52) + 68, // S ($53) + 68, // T ($54) + 68, // U ($55) + 68, // V ($56) + 68, // W ($57) + 68, // X ($58) + 68, // Y ($59) + 68, // Z ($5A) + 2, // [ ($5B) + 2, // \ ($5C) + 2, // ] ($5D) + 2, // ^ ($5E) + 68, // _ ($5F) + 2, // ` ($60) + 84, // a ($61) + 84, // b ($62) + 84, // c ($63) + 84, // d ($64) + 84, // e ($65) + 84, // f ($66) + 68, // g ($67) + 68, // h ($68) + 68, // i ($69) + 68, // j ($6A) + 68, // k ($6B) + 68, // l ($6C) + 68, // m ($6D) + 68, // n ($6E) + 68, // o ($6F) + 68, // p ($70) + 68, // q ($71) + 68, // r ($72) + 68, // s ($73) + 68, // t ($74) + 68, // u ($75) + 68, // v ($76) + 68, // w ($77) + 68, // x ($78) + 68, // y ($79) + 68, // z ($7A) + 2, // { ($7B) + 2, // | ($7C) + 2, // } ($7D) + 2, // ~ ($7E) + 0, //  ($7F) +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsOperator(int c) { + return c < 128 && (character_classification[c] & 2); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static bool IsDigit(int c) { + return c < 128 && (character_classification[c] & 8); +} + +static bool IsHexDigit(int c) { + return c < 128 && (character_classification[c] & 16); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int CheckHollywoodFoldPoint(char const *token) { + if (!strcmp(token, "function")) { + return 1; + } + if (!strcmp(token, "endfunction")) { + return -1; + } + return 0; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerHollywood +struct OptionsHollywood { + bool fold; + bool foldCompact; + OptionsHollywood() { + fold = false; + foldCompact = false; + } +}; + +static const char * const hollywoodWordListDesc[] = { + "Hollywood keywords", + "Hollywood standard API functions", + "Hollywood plugin API functions", + "Hollywood plugin methods", + 0 +}; + +struct OptionSetHollywood : public OptionSet { + OptionSetHollywood(const char * const wordListDescriptions[]) { + DefineProperty("fold", &OptionsHollywood::fold); + DefineProperty("fold.compact", &OptionsHollywood::foldCompact); + DefineWordListSets(wordListDescriptions); + } +}; + +class LexerHollywood : public DefaultLexer { + int (*CheckFoldPoint)(char const *); + WordList keywordlists[4]; + OptionsHollywood options; + OptionSetHollywood osHollywood; +public: + LexerHollywood(int (*CheckFoldPoint_)(char const *), const char * const wordListDescriptions[]) : + DefaultLexer("hollywood", SCLEX_HOLLYWOOD), + CheckFoldPoint(CheckFoldPoint_), + osHollywood(wordListDescriptions) { + } + virtual ~LexerHollywood() { + } + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char * SCI_METHOD PropertyNames() override { + return osHollywood.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osHollywood.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osHollywood.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char* key) override { + return osHollywood.PropertyGet(key); + } + const char * SCI_METHOD DescribeWordListSets() override { + return osHollywood.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + static ILexer5 *LexerFactoryHollywood() { + return new LexerHollywood(CheckHollywoodFoldPoint, hollywoodWordListDesc); + } +}; + +Sci_Position SCI_METHOD LexerHollywood::PropertySet(const char *key, const char *val) { + if (osHollywood.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerHollywood::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywordlists[0]; + break; + case 1: + wordListN = &keywordlists[1]; + break; + case 2: + wordListN = &keywordlists[2]; + break; + case 3: + wordListN = &keywordlists[3]; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerHollywood::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + styler.StartAt(startPos); + bool inString = false; + + StyleContext sc(startPos, length, initStyle, styler); + + // Can't use sc.More() here else we miss the last character + for (; ; sc.Forward()) + { + if (sc.atLineStart) inString = false; + + if (sc.ch == '\"' && sc.chPrev != '\\') inString = !inString; + + if (sc.state == SCE_HOLLYWOOD_IDENTIFIER) { + if (!IsIdentifier(sc.ch)) { + char s[100]; + int kstates[4] = { + SCE_HOLLYWOOD_KEYWORD, + SCE_HOLLYWOOD_STDAPI, + SCE_HOLLYWOOD_PLUGINAPI, + SCE_HOLLYWOOD_PLUGINMETHOD, + }; + sc.GetCurrentLowered(s, sizeof(s)); + for (int i = 0; i < 4; i++) { + if (keywordlists[i].InList(s)) { + sc.ChangeState(kstates[i]); + } + } + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + } + } else if (sc.state == SCE_HOLLYWOOD_OPERATOR) { + + // always reset to default on operators because otherwise + // comments won't be recognized in sequences like "+/* Hello*/" + // --> "+/*" would be recognized as a sequence of operators + + // if (!IsOperator(sc.ch)) sc.SetState(SCE_HOLLYWOOD_DEFAULT); + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + + } else if (sc.state == SCE_HOLLYWOOD_PREPROCESSOR) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + } else if (sc.state == SCE_HOLLYWOOD_CONSTANT) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + } else if (sc.state == SCE_HOLLYWOOD_NUMBER) { + if (!IsDigit(sc.ch) && sc.ch != '.') + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + } else if (sc.state == SCE_HOLLYWOOD_HEXNUMBER) { + if (!IsHexDigit(sc.ch)) + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + } else if (sc.state == SCE_HOLLYWOOD_STRING) { + if (sc.ch == '"') { + sc.ForwardSetState(SCE_HOLLYWOOD_DEFAULT); + } + if (sc.atLineEnd) { + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + } + } else if (sc.state == SCE_HOLLYWOOD_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_HOLLYWOOD_DEFAULT); + } + } else if (sc.state == SCE_HOLLYWOOD_COMMENTBLOCK) { + if (sc.Match("*/") && !inString) { + sc.Forward(); + sc.ForwardSetState(SCE_HOLLYWOOD_DEFAULT); + } + } else if (sc.state == SCE_HOLLYWOOD_STRINGBLOCK) { + if (sc.Match("]]") && !inString) { + sc.Forward(); + sc.ForwardSetState(SCE_HOLLYWOOD_DEFAULT); + } + } + + if (sc.state == SCE_HOLLYWOOD_DEFAULT) { + if (sc.Match(';')) { + sc.SetState(SCE_HOLLYWOOD_COMMENT); + } else if (sc.Match("/*")) { + sc.SetState(SCE_HOLLYWOOD_COMMENTBLOCK); + sc.Forward(); + } else if (sc.Match("[[")) { + sc.SetState(SCE_HOLLYWOOD_STRINGBLOCK); + sc.Forward(); + } else if (sc.Match('"')) { + sc.SetState(SCE_HOLLYWOOD_STRING); + } else if (sc.Match('$')) { + sc.SetState(SCE_HOLLYWOOD_HEXNUMBER); + } else if (sc.Match("0x") || sc.Match("0X")) { // must be before IsDigit() because of 0x + sc.SetState(SCE_HOLLYWOOD_HEXNUMBER); + sc.Forward(); + } else if (sc.ch == '.' && (sc.chNext >= '0' && sc.chNext <= '9')) { // ".1234" style numbers + sc.SetState(SCE_HOLLYWOOD_NUMBER); + sc.Forward(); + } else if (IsDigit(sc.ch)) { + sc.SetState(SCE_HOLLYWOOD_NUMBER); + } else if (sc.Match('#')) { + sc.SetState(SCE_HOLLYWOOD_CONSTANT); + } else if (sc.Match('@')) { + sc.SetState(SCE_HOLLYWOOD_PREPROCESSOR); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_HOLLYWOOD_OPERATOR); + } else if (IsIdentifier(sc.ch)) { + sc.SetState(SCE_HOLLYWOOD_IDENTIFIER); + } + } + + if (!sc.More()) + break; + } + sc.Complete(); +} + +void SCI_METHOD LexerHollywood::Fold(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + Sci_PositionU lengthDoc = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int done = 0; + char word[256]; + int wordlen = 0; + + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (!done) { + if (wordlen) { // are we scanning a token already? + word[wordlen] = static_cast(LowerCase(ch)); + if (!IsIdentifier(ch)) { // done with token + word[wordlen] = '\0'; + levelCurrent += CheckFoldPoint(word); + done = 1; + } else if (wordlen < 255) { + wordlen++; + } + } else { // start scanning at first non-whitespace character + if (!IsSpace(ch)) { + if (style != SCE_HOLLYWOOD_COMMENTBLOCK && IsIdentifier(ch)) { + word[0] = static_cast(LowerCase(ch)); + wordlen = 1; + } else // done with this line + done = 1; + } + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && options.foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + done = 0; + wordlen = 0; + } + if (!IsSpace(ch)) { + visibleChars++; + } + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +extern const LexerModule lmHollywood(SCLEX_HOLLYWOOD, LexerHollywood::LexerFactoryHollywood, "hollywood", hollywoodWordListDesc); diff --git a/src/lexilla/lexers/LexIndent.cxx b/src/lexilla/lexers/LexIndent.cxx new file mode 100644 index 000000000..94d160d17 --- /dev/null +++ b/src/lexilla/lexers/LexIndent.cxx @@ -0,0 +1,74 @@ +// Scintilla source code edit control +/** @file LexIndent.cxx + ** Lexer for no language. Used for indentation-based folding of files. + **/ +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static void ColouriseIndentDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], + Accessor &styler) { + // Indent language means all style bytes are 0 so just mark the end - no need to fill in. + if (length > 0) { + styler.StartAt(startPos + length - 1); + styler.StartSegment(startPos + length - 1); + styler.ColourTo(startPos + length - 1, 0); + } +} + +static void FoldIndentDoc(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[], Accessor &styler) { + int visibleCharsCurrent, visibleCharsNext; + int levelCurrent, levelNext; + Sci_PositionU i, lineEnd; + Sci_PositionU lengthDoc = startPos + length; + Sci_Position lineCurrent = styler.GetLine(startPos); + + i = styler.LineStart(lineCurrent ); + lineEnd = styler.LineStart(lineCurrent+1)-1; + if(lineEnd>=lengthDoc) lineEnd = lengthDoc-1; + while(styler[lineEnd]=='\n' || styler[lineEnd]=='\r') lineEnd--; + for(visibleCharsCurrent=0, levelCurrent=SC_FOLDLEVELBASE; !visibleCharsCurrent && i<=lineEnd; i++){ + if(isspacechar(styler[i])) levelCurrent++; + else visibleCharsCurrent=1; + } + + for(; i=lengthDoc) lineEnd = lengthDoc-1; + while(styler[lineEnd]=='\n' || styler[lineEnd]=='\r') lineEnd--; + for(visibleCharsNext=0, levelNext=SC_FOLDLEVELBASE; !visibleCharsNext && i<=lineEnd; i++){ + if(isspacechar(styler[i])) levelNext++; + else visibleCharsNext=1; + } + int lev = levelCurrent; + if(!visibleCharsCurrent) lev |= SC_FOLDLEVELWHITEFLAG; + else if(levelNext > levelCurrent) lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(lineCurrent, lev); + levelCurrent = levelNext; + visibleCharsCurrent = visibleCharsNext; + } +} + +extern const LexerModule lmIndent(SCLEX_INDENT, ColouriseIndentDoc, "indent", FoldIndentDoc); diff --git a/src/lexilla/lexers/LexInno.cxx b/src/lexilla/lexers/LexInno.cxx new file mode 100644 index 000000000..91e110675 --- /dev/null +++ b/src/lexilla/lexers/LexInno.cxx @@ -0,0 +1,378 @@ +// Scintilla source code edit control +/** @file LexInno.cxx + ** Lexer for Inno Setup scripts. + **/ +// Written by Friedrich Vedder , using code from LexOthers.cxx. +// Modified by Michael Heath. +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static bool innoIsBlank(int ch) { + return (ch == ' ') || (ch == '\t'); +} + +static bool innoNextNotBlankIs(Sci_Position i, Accessor &styler, char needle) { + char ch; + + while (i < styler.Length()) { + ch = styler.SafeGetCharAt(i); + + if (ch == needle) + return true; + + if (!innoIsBlank(ch)) + return false; + + i++; + } + return false; +} + +static void ColouriseInnoDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *keywordLists[], Accessor &styler) { + int state = SCE_INNO_DEFAULT; + char chPrev; + char ch = 0; + char chNext = styler[startPos]; + Sci_Position lengthDoc = startPos + length; + char *buffer = new char[length + 1]; + Sci_Position bufferCount = 0; + bool isBOL, isEOL, isWS, isBOLWS = 0; + + // Save line state later with bitState and bitand with bit... to get line state + int bitState = 0; + int const bitCode = 1, bitMessages = 2, bitCommentCurly = 4, bitCommentRound = 8; + + // Get keyword lists + WordList §ionKeywords = *keywordLists[0]; + WordList &standardKeywords = *keywordLists[1]; + WordList ¶meterKeywords = *keywordLists[2]; + WordList &preprocessorKeywords = *keywordLists[3]; + WordList &pascalKeywords = *keywordLists[4]; + WordList &userKeywords = *keywordLists[5]; + + // Get line state + Sci_Position curLine = styler.GetLine(startPos); + int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; + bool isCode = (curLineState & bitCode); + bool isMessages = (curLineState & bitMessages); + bool isCommentCurly = (curLineState & bitCommentCurly); + bool isCommentRound = (curLineState & bitCommentRound); + bool isCommentSlash = false; + + // Continue Pascal multline comment state + if (isCommentCurly || isCommentRound) + state = SCE_INNO_COMMENT_PASCAL; + + // Go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + + for (Sci_Position i = startPos; i < lengthDoc; i++) { + chPrev = ch; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + + isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n'); + isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t')); + isEOL = (ch == '\n' || ch == '\r'); + isWS = (ch == ' ' || ch == '\t'); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Remember the line state for future incremental lexing + curLine = styler.GetLine(i); + bitState = 0; + + if (isCode) + bitState |= bitCode; + + if (isMessages) + bitState |= bitMessages; + + if (isCommentCurly) + bitState |= bitCommentCurly; + + if (isCommentRound) + bitState |= bitCommentRound; + + styler.SetLineState(curLine, bitState); + } + + switch(state) { + case SCE_INNO_DEFAULT: + if (!isCode && ch == ';' && isBOLWS) { + // Start of a comment + state = SCE_INNO_COMMENT; + styler.ColourTo(i, SCE_INNO_COMMENT); + } else if (ch == '[' && isBOLWS) { + // Start of a section name + state = SCE_INNO_SECTION; + bufferCount = 0; + } else if (ch == '#' && isBOLWS) { + // Start of a preprocessor directive + state = SCE_INNO_PREPROC; + } else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') { + // Start of an inline expansion + state = SCE_INNO_INLINE_EXPANSION; + } else if (isCode && ch == '{') { + // Start of a Pascal comment + state = SCE_INNO_COMMENT_PASCAL; + isCommentCurly = true; + styler.ColourTo(i, SCE_INNO_COMMENT_PASCAL); + } else if (isCode && (ch == '(' && chNext == '*')) { + // Start of a Pascal comment + state = SCE_INNO_COMMENT_PASCAL; + isCommentRound = true; + styler.ColourTo(i + 1, SCE_INNO_COMMENT_PASCAL); + } else if (isCode && ch == '/' && chNext == '/') { + // Start of C-style comment + state = SCE_INNO_COMMENT_PASCAL; + isCommentSlash = true; + styler.ColourTo(i + 1, SCE_INNO_COMMENT_PASCAL); + } else if (!isMessages && ch == '"') { + // Start of a double-quote string + state = SCE_INNO_STRING_DOUBLE; + styler.ColourTo(i, SCE_INNO_STRING_DOUBLE); + } else if (!isMessages && ch == '\'') { + // Start of a single-quote string + state = SCE_INNO_STRING_SINGLE; + styler.ColourTo(i, SCE_INNO_STRING_SINGLE); + } else if (!isMessages && IsASCII(ch) && (isalpha(ch) || (ch == '_'))) { + // Start of an identifier + state = SCE_INNO_IDENTIFIER; + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + // Style it the default style + styler.ColourTo(i, SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_COMMENT: + if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i - 1, SCE_INNO_COMMENT); + styler.ColourTo(i, SCE_INNO_DEFAULT); + } else { + styler.ColourTo(i, SCE_INNO_COMMENT); + } + break; + + case SCE_INNO_IDENTIFIER: + if (IsASCII(ch) && (isalnum(ch) || (ch == '_'))) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a keyword + if (!isCode && standardKeywords.InList(buffer) && innoNextNotBlankIs(i, styler, '=')) { + styler.ColourTo(i - 1, SCE_INNO_KEYWORD); + } else if (!isCode && parameterKeywords.InList(buffer) && innoNextNotBlankIs(i, styler, ':')) { + styler.ColourTo(i - 1, SCE_INNO_PARAMETER); + } else if (isCode && pascalKeywords.InList(buffer)) { + styler.ColourTo(i - 1, SCE_INNO_KEYWORD_PASCAL); + } else if (!isCode && userKeywords.InList(buffer)) { + styler.ColourTo(i - 1, SCE_INNO_KEYWORD_USER); + } else { + styler.ColourTo(i - 1, SCE_INNO_DEFAULT); + } + + // Push back the faulty character + chNext = styler[i--]; + ch = chPrev; + } + break; + + case SCE_INNO_SECTION: + if (ch == ']') { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a section name + if (sectionKeywords.InList(buffer)) { + styler.ColourTo(i, SCE_INNO_SECTION); + isCode = !CompareCaseInsensitive(buffer, "code"); + + isMessages = isCode ? false : ( + !CompareCaseInsensitive(buffer, "custommessages") + || !CompareCaseInsensitive(buffer, "messages")); + } else { + styler.ColourTo(i, SCE_INNO_DEFAULT); + } + } else if (IsASCII(ch) && (isalnum(ch) || (ch == '_'))) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i, SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_PREPROC: + if (isWS || isEOL) { + if (IsASCII(chPrev) && isalpha(chPrev)) { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a preprocessor directive + if (preprocessorKeywords.InList(buffer)) { + styler.ColourTo(i - 1, SCE_INNO_PREPROC); + } else { + styler.ColourTo(i - 1, SCE_INNO_DEFAULT); + } + + // Push back the faulty character + chNext = styler[i--]; + ch = chPrev; + } + } else if (IsASCII(ch) && isalpha(ch)) { + if (chPrev == '#' || chPrev == ' ' || chPrev == '\t') + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + } + break; + + case SCE_INNO_STRING_DOUBLE: + if (ch == '"') { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i, SCE_INNO_STRING_DOUBLE); + } else if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i - 1, SCE_INNO_STRING_DOUBLE); + styler.ColourTo(i, SCE_INNO_DEFAULT); + } else { + styler.ColourTo(i, SCE_INNO_STRING_DOUBLE); + } + break; + + case SCE_INNO_STRING_SINGLE: + if (ch == '\'') { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i, SCE_INNO_STRING_SINGLE); + } else if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i - 1, SCE_INNO_STRING_SINGLE); + styler.ColourTo(i, SCE_INNO_DEFAULT); + } else { + styler.ColourTo(i, SCE_INNO_STRING_SINGLE); + } + break; + + case SCE_INNO_INLINE_EXPANSION: + if (ch == '}') { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i, SCE_INNO_INLINE_EXPANSION); + } else if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i, SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_COMMENT_PASCAL: + if (isCommentSlash) { + if (isEOL) { + state = SCE_INNO_DEFAULT; + isCommentSlash = false; + styler.ColourTo(i - 1, SCE_INNO_COMMENT_PASCAL); + styler.ColourTo(i, SCE_INNO_DEFAULT); + } else { + styler.ColourTo(i, SCE_INNO_COMMENT_PASCAL); + } + } else if (isCommentCurly) { + if (ch == '}') { + state = SCE_INNO_DEFAULT; + isCommentCurly = false; + } + styler.ColourTo(i, SCE_INNO_COMMENT_PASCAL); + } else if (isCommentRound) { + if (ch == ')' && chPrev == '*') { + state = SCE_INNO_DEFAULT; + isCommentRound = false; + } + styler.ColourTo(i, SCE_INNO_COMMENT_PASCAL); + } + break; + + } + } + delete []buffer; +} + +static const char * const innoWordListDesc[] = { + "Sections", + "Keywords", + "Parameters", + "Preprocessor directives", + "Pascal keywords", + "User defined keywords", + 0 +}; + +static void FoldInnoDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { + Sci_PositionU endPos = startPos + length; + char chNext = styler[startPos]; + + Sci_Position lineCurrent = styler.GetLine(startPos); + + bool sectionFlag = false; + int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE; + int level; + + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler[i + 1]; + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + int style = styler.StyleAt(i); + + if (style == SCE_INNO_SECTION) + sectionFlag = true; + + if (atEOL || i == endPos - 1) { + if (sectionFlag) { + level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + if (level == levelPrev) + styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); + } else { + level = levelPrev & SC_FOLDLEVELNUMBERMASK; + if (levelPrev & SC_FOLDLEVELHEADERFLAG) + level++; + } + + styler.SetLevel(lineCurrent, level); + + levelPrev = level; + lineCurrent++; + sectionFlag = false; + } + } +} + +extern const LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc); diff --git a/src/lexilla/lexers/LexJSON.cxx b/src/lexilla/lexers/LexJSON.cxx new file mode 100644 index 000000000..8e3374aee --- /dev/null +++ b/src/lexilla/lexers/LexJSON.cxx @@ -0,0 +1,507 @@ +// Scintilla source code edit control +/** + * @file LexJSON.cxx + * @date February 19, 2016 + * @brief Lexer for JSON and JSON-LD formats + * @author nkmathew + * + * The License.txt file describes the conditions under which this software may + * be distributed. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + +const char *const JSONWordListDesc[] = { + "JSON Keywords", + "JSON-LD Keywords", + 0 +}; + +/** + * Used to detect compact IRI/URLs in JSON-LD without first looking ahead for the + * colon separating the prefix and suffix + * + * https://www.w3.org/TR/json-ld/#dfn-compact-iri + */ +struct CompactIRI { + int colonCount; + bool foundInvalidChar; + CharacterSet setCompactIRI; + CompactIRI() { + colonCount = 0; + foundInvalidChar = false; + setCompactIRI = CharacterSet(CharacterSet::setAlpha, "$_-"); + } + void resetState() { + colonCount = 0; + foundInvalidChar = false; + } + void checkChar(int ch) { + if (ch == ':') { + colonCount++; + } else { + foundInvalidChar |= !setCompactIRI.Contains(ch); + } + } + bool shouldHighlight() const { + return !foundInvalidChar && colonCount == 1; + } +}; + +/** + * Keeps track of escaped characters in strings as per: + * + * https://tools.ietf.org/html/rfc7159#section-7 + */ +struct EscapeSequence { + int digitsLeft; + CharacterSet setHexDigits; + CharacterSet setEscapeChars; + EscapeSequence() { + digitsLeft = 0; + setHexDigits = CharacterSet(CharacterSet::setDigits, "ABCDEFabcdef"); + setEscapeChars = CharacterSet(CharacterSet::setNone, "\\\"tnbfru/"); + } + // Returns true if the following character is a valid escaped character + bool newSequence(int nextChar) { + digitsLeft = 0; + if (nextChar == 'u') { + digitsLeft = 5; + } else if (!setEscapeChars.Contains(nextChar)) { + return false; + } + return true; + } + bool atEscapeEnd() const { + return digitsLeft <= 0; + } + bool isInvalidChar(int currChar) const { + return !setHexDigits.Contains(currChar); + } +}; + +struct OptionsJSON { + bool foldCompact; + bool fold; + bool allowComments; + bool escapeSequence; + OptionsJSON() { + foldCompact = false; + fold = false; + allowComments = false; + escapeSequence = false; + } +}; + +struct OptionSetJSON : public OptionSet { + OptionSetJSON() { + DefineProperty("lexer.json.escape.sequence", &OptionsJSON::escapeSequence, + "Set to 1 to enable highlighting of escape sequences in strings"); + + DefineProperty("lexer.json.allow.comments", &OptionsJSON::allowComments, + "Set to 1 to enable highlighting of line/block comments in JSON"); + + DefineProperty("fold.compact", &OptionsJSON::foldCompact); + DefineProperty("fold", &OptionsJSON::fold); + DefineWordListSets(JSONWordListDesc); + } +}; + +class LexerJSON : public DefaultLexer { + OptionsJSON options; + OptionSetJSON optSetJSON; + EscapeSequence escapeSeq; + WordList keywordsJSON; + WordList keywordsJSONLD; + CharacterSet setOperators; + CharacterSet setURL; + CharacterSet setKeywordJSONLD; + CharacterSet setKeywordJSON; + CompactIRI compactIRI; + + static bool IsNextNonWhitespace(LexAccessor &styler, Sci_Position start, char ch) { + Sci_Position i = 0; + while (i < 50) { + i++; + char curr = styler.SafeGetCharAt(start+i, '\0'); + char next = styler.SafeGetCharAt(start+i+1, '\0'); + bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n'); + if (curr == ch) { + return true; + } else if (!isspacechar(curr) || atEOL) { + return false; + } + } + return false; + } + + /** + * Looks for the colon following the end quote + * + * Assumes property names of lengths no longer than a 100 characters. + * The colon is also expected to be less than 50 spaces after the end + * quote for the string to be considered a property name + */ + static bool AtPropertyName(LexAccessor &styler, Sci_Position start) { + Sci_Position i = 0; + bool escaped = false; + while (i < 100) { + i++; + char curr = styler.SafeGetCharAt(start+i, '\0'); + if (escaped) { + escaped = false; + continue; + } + escaped = curr == '\\'; + if (curr == '"') { + return IsNextNonWhitespace(styler, start+i, ':'); + } else if (!curr) { + return false; + } + } + return false; + } + + static bool IsNextWordInList(WordList &keywordList, CharacterSet wordSet, + StyleContext &context, LexAccessor &styler) { + char word[51]; + Sci_Position currPos = (Sci_Position) context.currentPos; + int i = 0; + while (i < 50) { + char ch = styler.SafeGetCharAt(currPos + i); + if (!wordSet.Contains(ch)) { + break; + } + word[i] = ch; + i++; + } + word[i] = '\0'; + return keywordList.InList(word); + } + + public: + LexerJSON() : + DefaultLexer("json", SCLEX_JSON), + setOperators(CharacterSet::setNone, "[{}]:,"), + setURL(CharacterSet::setAlphaNum, "-._~:/?#[]@!$&'()*+,),="), + setKeywordJSONLD(CharacterSet::setAlpha, ":@"), + setKeywordJSON(CharacterSet::setAlpha, "$_") { + } + virtual ~LexerJSON() {} + int SCI_METHOD Version() const override { + return lvRelease5; + } + void SCI_METHOD Release() override { + delete this; + } + const char *SCI_METHOD PropertyNames() override { + return optSetJSON.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return optSetJSON.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) override { + return optSetJSON.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override { + if (optSetJSON.PropertySet(&options, key, val)) { + return 0; + } + return -1; + } + const char * SCI_METHOD PropertyGet(const char *key) override { + return optSetJSON.PropertyGet(key); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywordsJSON; + break; + case 1: + wordListN = &keywordsJSONLD; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + if (wordListN->Set(wl)) { + firstModification = 0; + } + } + return firstModification; + } + void *SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + static ILexer5 *LexerFactoryJSON() { + return new LexerJSON; + } + const char *SCI_METHOD DescribeWordListSets() override { + return optSetJSON.DescribeWordListSets(); + } + void SCI_METHOD Lex(Sci_PositionU startPos, + Sci_Position length, + int initStyle, + IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, + Sci_Position length, + int initStyle, + IDocument *pAccess) override; +}; + +void SCI_METHOD LexerJSON::Lex(Sci_PositionU startPos, + Sci_Position length, + int initStyle, + IDocument *pAccess) { + LexAccessor styler(pAccess); + StyleContext context(startPos, length, initStyle, styler); + int stringStyleBefore = SCE_JSON_STRING; + while (context.More()) { + switch (context.state) { + case SCE_JSON_BLOCKCOMMENT: + if (context.Match("*/")) { + context.Forward(); + context.ForwardSetState(SCE_JSON_DEFAULT); + } + break; + case SCE_JSON_LINECOMMENT: + if (context.MatchLineEnd()) { + context.SetState(SCE_JSON_DEFAULT); + } + break; + case SCE_JSON_STRINGEOL: + if (context.atLineStart) { + context.SetState(SCE_JSON_DEFAULT); + } + break; + case SCE_JSON_ESCAPESEQUENCE: + escapeSeq.digitsLeft--; + if (!escapeSeq.atEscapeEnd()) { + if (escapeSeq.isInvalidChar(context.ch)) { + context.SetState(SCE_JSON_ERROR); + } + break; + } + if (context.ch == '"') { + context.SetState(stringStyleBefore); + context.ForwardSetState(SCE_JSON_DEFAULT); + } else if (context.ch == '\\') { + if (!escapeSeq.newSequence(context.chNext)) { + context.SetState(SCE_JSON_ERROR); + } + context.Forward(); + } else { + context.SetState(stringStyleBefore); + if (context.atLineEnd) { + context.ChangeState(SCE_JSON_STRINGEOL); + } + } + break; + case SCE_JSON_PROPERTYNAME: + case SCE_JSON_STRING: + if (context.ch == '"') { + if (compactIRI.shouldHighlight()) { + context.ChangeState(SCE_JSON_COMPACTIRI); + context.ForwardSetState(SCE_JSON_DEFAULT); + compactIRI.resetState(); + } else { + context.ForwardSetState(SCE_JSON_DEFAULT); + } + } else if (context.atLineEnd) { + context.ChangeState(SCE_JSON_STRINGEOL); + } else if (context.ch == '\\') { + stringStyleBefore = context.state; + if (options.escapeSequence) { + context.SetState(SCE_JSON_ESCAPESEQUENCE); + if (!escapeSeq.newSequence(context.chNext)) { + context.SetState(SCE_JSON_ERROR); + } + } + context.Forward(); + } else if (context.Match("https://") || + context.Match("http://") || + context.Match("ssh://") || + context.Match("git://") || + context.Match("svn://") || + context.Match("ftp://") || + context.Match("mailto:")) { + // Handle most common URI schemes only + stringStyleBefore = context.state; + context.SetState(SCE_JSON_URI); + } else if (context.ch == '@') { + // https://www.w3.org/TR/json-ld/#dfn-keyword + if (IsNextWordInList(keywordsJSONLD, setKeywordJSONLD, context, styler)) { + stringStyleBefore = context.state; + context.SetState(SCE_JSON_LDKEYWORD); + } + } else { + compactIRI.checkChar(context.ch); + } + break; + case SCE_JSON_LDKEYWORD: + case SCE_JSON_URI: + if ((!setKeywordJSONLD.Contains(context.ch) && + (context.state == SCE_JSON_LDKEYWORD)) || + (!setURL.Contains(context.ch))) { + context.SetState(stringStyleBefore); + } + if (context.ch == '"') { + context.ForwardSetState(SCE_JSON_DEFAULT); + } else if (context.atLineEnd) { + context.ChangeState(SCE_JSON_STRINGEOL); + } + break; + case SCE_JSON_OPERATOR: + case SCE_JSON_NUMBER: + context.SetState(SCE_JSON_DEFAULT); + break; + case SCE_JSON_ERROR: + if (context.MatchLineEnd()) { + context.SetState(SCE_JSON_DEFAULT); + } + break; + case SCE_JSON_KEYWORD: + if (!setKeywordJSON.Contains(context.ch)) { + context.SetState(SCE_JSON_DEFAULT); + } + break; + } + if (context.state == SCE_JSON_DEFAULT) { + if (context.ch == '"') { + compactIRI.resetState(); + context.SetState(SCE_JSON_STRING); + Sci_Position currPos = static_cast(context.currentPos); + if (AtPropertyName(styler, currPos)) { + context.SetState(SCE_JSON_PROPERTYNAME); + } + } else if (setOperators.Contains(context.ch)) { + context.SetState(SCE_JSON_OPERATOR); + } else if (options.allowComments && context.Match("/*")) { + context.SetState(SCE_JSON_BLOCKCOMMENT); + context.Forward(); + } else if (options.allowComments && context.Match("//")) { + context.SetState(SCE_JSON_LINECOMMENT); + } else if (setKeywordJSON.Contains(context.ch)) { + if (IsNextWordInList(keywordsJSON, setKeywordJSON, context, styler)) { + context.SetState(SCE_JSON_KEYWORD); + } + } + bool numberStart = + IsADigit(context.ch) && (context.chPrev == '+'|| + context.chPrev == '-' || + context.atLineStart || + IsASpace(context.chPrev) || + setOperators.Contains(context.chPrev)); + bool exponentPart = + tolower(context.ch) == 'e' && + IsADigit(context.chPrev) && + (IsADigit(context.chNext) || + context.chNext == '+' || + context.chNext == '-'); + bool signPart = + (context.ch == '-' || context.ch == '+') && + ((tolower(context.chPrev) == 'e' && IsADigit(context.chNext)) || + ((IsASpace(context.chPrev) || setOperators.Contains(context.chPrev)) + && IsADigit(context.chNext))); + bool adjacentDigit = + IsADigit(context.ch) && IsADigit(context.chPrev); + bool afterExponent = IsADigit(context.ch) && tolower(context.chPrev) == 'e'; + bool dotPart = context.ch == '.' && + IsADigit(context.chPrev) && + IsADigit(context.chNext); + bool afterDot = IsADigit(context.ch) && context.chPrev == '.'; + if (numberStart || + exponentPart || + signPart || + adjacentDigit || + dotPart || + afterExponent || + afterDot) { + context.SetState(SCE_JSON_NUMBER); + } else if (context.state == SCE_JSON_DEFAULT && !IsASpace(context.ch)) { + context.SetState(SCE_JSON_ERROR); + } + } + context.Forward(); + } + context.Complete(); +} + +void SCI_METHOD LexerJSON::Fold(Sci_PositionU startPos, + Sci_Position length, + int, + IDocument *pAccess) { + if (!options.fold) { + return; + } + LexAccessor styler(pAccess); + Sci_PositionU currLine = styler.GetLine(startPos); + Sci_PositionU endPos = startPos + length; + int currLevel = SC_FOLDLEVELBASE; + if (currLine > 0) + currLevel = styler.LevelAt(currLine - 1) >> 16; + int nextLevel = currLevel; + int visibleChars = 0; + for (Sci_PositionU i = startPos; i < endPos; i++) { + char curr = styler.SafeGetCharAt(i); + char next = styler.SafeGetCharAt(i+1); + bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n'); + if (styler.StyleAt(i) == SCE_JSON_OPERATOR) { + if (curr == '{' || curr == '[') { + nextLevel++; + } else if (curr == '}' || curr == ']') { + nextLevel--; + } + } + if (atEOL || i == (endPos-1)) { + int level = currLevel | nextLevel << 16; + if (!visibleChars && options.foldCompact) { + level |= SC_FOLDLEVELWHITEFLAG; + } else if (nextLevel > currLevel) { + level |= SC_FOLDLEVELHEADERFLAG; + } + if (level != styler.LevelAt(currLine)) { + styler.SetLevel(currLine, level); + } + currLine++; + currLevel = nextLevel; + visibleChars = 0; + } + if (!isspacechar(curr)) { + visibleChars++; + } + } +} + +} + +extern const LexerModule lmJSON(SCLEX_JSON, + LexerJSON::LexerFactoryJSON, + "json", + JSONWordListDesc); diff --git a/src/lexilla/lexers/LexJulia.cxx b/src/lexilla/lexers/LexJulia.cxx new file mode 100644 index 000000000..ebc67f854 --- /dev/null +++ b/src/lexilla/lexers/LexJulia.cxx @@ -0,0 +1,1262 @@ +// Scintilla source code edit control +// Encoding: UTF-8 +/** @file LexJulia.cxx + ** Lexer for Julia. + ** Reusing code from LexMatlab, LexPython and LexRust + ** + ** Written by Bertrand Lacoste + ** + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "CharacterCategory.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +static const int MAX_JULIA_IDENT_CHARS = 1023; + +// Options used for LexerJulia +struct OptionsJulia { + bool fold; + bool foldComment; + bool foldCompact; + bool foldDocstring; + bool foldSyntaxBased; + bool highlightTypeannotation; + bool highlightLexerror; + OptionsJulia() { + fold = true; + foldComment = true; + foldCompact = false; + foldDocstring = true; + foldSyntaxBased = true; + highlightTypeannotation = false; + highlightLexerror = false; + } +}; + +const char * const juliaWordLists[] = { + "Primary keywords and identifiers", + "Built in types", + "Other keywords", + "Built in functions", + 0, +}; + +struct OptionSetJulia : public OptionSet { + OptionSetJulia() { + DefineProperty("fold", &OptionsJulia::fold); + + DefineProperty("fold.compact", &OptionsJulia::foldCompact); + + DefineProperty("fold.comment", &OptionsJulia::foldComment); + + DefineProperty("fold.julia.docstring", &OptionsJulia::foldDocstring, + "Fold multiline triple-doublequote strings, usually used to document a function or type above the definition."); + + DefineProperty("fold.julia.syntax.based", &OptionsJulia::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("lexer.julia.highlight.typeannotation", &OptionsJulia::highlightTypeannotation, + "This option enables highlighting of the type identifier after `::`."); + + DefineProperty("lexer.julia.highlight.lexerror", &OptionsJulia::highlightLexerror, + "This option enables highlighting of syntax error int character or number definition."); + + DefineWordListSets(juliaWordLists); + } +}; + +LexicalClass juliaLexicalClasses[] = { + // Lexer Julia SCLEX_JULIA SCE_JULIA_: + 0, "SCE_JULIA_DEFAULT", "default", "White space", + 1, "SCE_JULIA_COMMENT", "comment", "Comment", + 2, "SCE_JULIA_NUMBER", "literal numeric", "Number", + 3, "SCE_JULIA_KEYWORD1", "keyword", "Reserved keywords", + 4, "SCE_JULIA_KEYWORD2", "identifier", "Builtin type names", + 5, "SCE_JULIA_KEYWORD3", "identifier", "Constants", + 6, "SCE_JULIA_CHAR", "literal string character", "Single quoted string", + 7, "SCE_JULIA_OPERATOR", "operator", "Operator", + 8, "SCE_JULIA_BRACKET", "bracket operator", "Bracket operator", + 9, "SCE_JULIA_IDENTIFIER", "identifier", "Identifier", + 10, "SCE_JULIA_STRING", "literal string", "Double quoted String", + 11, "SCE_JULIA_SYMBOL", "literal string symbol", "Symbol", + 12, "SCE_JULIA_MACRO", "macro preprocessor", "Macro", + 13, "SCE_JULIA_STRINGINTERP", "literal string interpolated", "String interpolation", + 14, "SCE_JULIA_DOCSTRING", "literal string documentation", "Docstring", + 15, "SCE_JULIA_STRINGLITERAL", "literal string", "String literal prefix", + 16, "SCE_JULIA_COMMAND", "literal string command", "Command", + 17, "SCE_JULIA_COMMANDLITERAL", "literal string command", "Command literal prefix", + 18, "SCE_JULIA_TYPEANNOT", "identifier type", "Type annotation identifier", + 19, "SCE_JULIA_LEXERROR", "lexer error", "Lexing error", + 20, "SCE_JULIA_KEYWORD4", "identifier", "Builtin function names", + 21, "SCE_JULIA_TYPEOPERATOR", "operator type", "Type annotation operator", +}; + +class LexerJulia : public DefaultLexer { + WordList keywords; + WordList identifiers2; + WordList identifiers3; + WordList identifiers4; + OptionsJulia options; + OptionSetJulia osJulia; +public: + explicit LexerJulia() : + DefaultLexer("julia", SCLEX_JULIA, juliaLexicalClasses, ELEMENTS(juliaLexicalClasses)) { + } + virtual ~LexerJulia() { + } + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char * SCI_METHOD PropertyNames() override { + return osJulia.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osJulia.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osJulia.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char * SCI_METHOD PropertyGet(const char *key) override { + return osJulia.PropertyGet(key); + } + const char * SCI_METHOD DescribeWordListSets() override { + return osJulia.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void * SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + + static ILexer5 *LexerFactoryJulia() { + return new LexerJulia(); + } +}; + +Sci_Position SCI_METHOD LexerJulia::PropertySet(const char *key, const char *val) { + if (osJulia.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerJulia::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &identifiers2; + break; + case 2: + wordListN = &identifiers3; + break; + case 3: + wordListN = &identifiers4; + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + if (wordListN->Set(wl)) { + firstModification = 0; + } + } + return firstModification; +} + +static inline bool IsJuliaOperator(int ch) { + if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || + ch == '-' || ch == '+' || ch == '=' || ch == '|' || + ch == '<' || ch == '>' || ch == '/' || ch == '~' || + ch == '\\' ) { + return true; + } + return false; +} + +// The list contains non-ascii unary operators +static inline bool IsJuliaUnaryOperator (int ch) { + if (ch == 0x00ac || ch == 0x221a || ch == 0x221b || + ch == 0x221c || ch == 0x22c6 || ch == 0x00b1 || + ch == 0x2213 ) { + return true; + } + return false; +} + +static inline bool IsJuliaParen (int ch) { + if (ch == '(' || ch == ')' || ch == '{' || ch == '}' || + ch == '[' || ch == ']' ) { + return true; + } + return false; +} + +// Unicode parsing from Julia source code: +// https://github.com/JuliaLang/julia/blob/master/src/flisp/julia_extensions.c +// keep the same function name to be easy to find again +static int is_wc_cat_id_start(uint32_t wc) { + const CharacterCategory cat = CategoriseCharacter((int) wc); + + return (cat == ccLu || cat == ccLl || + cat == ccLt || cat == ccLm || + cat == ccLo || cat == ccNl || + cat == ccSc || // allow currency symbols + // other symbols, but not arrows or replacement characters + (cat == ccSo && !(wc >= 0x2190 && wc <= 0x21FF) && + wc != 0xfffc && wc != 0xfffd && + wc != 0x233f && // notslash + wc != 0x00a6) || // broken bar + + // math symbol (category Sm) whitelist + (wc >= 0x2140 && wc <= 0x2a1c && + ((wc >= 0x2140 && wc <= 0x2144) || // ⅀, ⅁, ⅂, ⅃, ⅄ + wc == 0x223f || wc == 0x22be || wc == 0x22bf || // ∿, ⊾, ⊿ + wc == 0x22a4 || wc == 0x22a5 || // ⊤ ⊥ + + (wc >= 0x2200 && wc <= 0x2233 && + (wc == 0x2202 || wc == 0x2205 || wc == 0x2206 || // ∂, ∅, ∆ + wc == 0x2207 || wc == 0x220e || wc == 0x220f || // ∇, ∎, ∏ + wc == 0x2200 || wc == 0x2203 || wc == 0x2204 || // ∀, ∃, ∄ + wc == 0x2210 || wc == 0x2211 || // ∐, ∑ + wc == 0x221e || wc == 0x221f || // ∞, ∟ + wc >= 0x222b)) || // ∫, ∬, ∭, ∮, ∯, ∰, ∱, ∲, ∳ + + (wc >= 0x22c0 && wc <= 0x22c3) || // N-ary big ops: ⋀, ⋁, ⋂, ⋃ + (wc >= 0x25F8 && wc <= 0x25ff) || // ◸, ◹, ◺, ◻, ◼, ◽, ◾, ◿ + + (wc >= 0x266f && + (wc == 0x266f || wc == 0x27d8 || wc == 0x27d9 || // ♯, ⟘, ⟙ + (wc >= 0x27c0 && wc <= 0x27c1) || // ⟀, ⟁ + (wc >= 0x29b0 && wc <= 0x29b4) || // ⦰, ⦱, ⦲, ⦳, ⦴ + (wc >= 0x2a00 && wc <= 0x2a06) || // ⨀, ⨁, ⨂, ⨃, ⨄, ⨅, ⨆ + (wc >= 0x2a09 && wc <= 0x2a16) || // ⨉, ⨊, ⨋, ⨌, ⨍, ⨎, ⨏, ⨐, ⨑, ⨒, ⨓, ⨔, ⨕, ⨖ + wc == 0x2a1b || wc == 0x2a1c)))) || // ⨛, ⨜ + + (wc >= 0x1d6c1 && // variants of \nabla and \partial + (wc == 0x1d6c1 || wc == 0x1d6db || + wc == 0x1d6fb || wc == 0x1d715 || + wc == 0x1d735 || wc == 0x1d74f || + wc == 0x1d76f || wc == 0x1d789 || + wc == 0x1d7a9 || wc == 0x1d7c3)) || + + // super- and subscript +-=() + (wc >= 0x207a && wc <= 0x207e) || + (wc >= 0x208a && wc <= 0x208e) || + + // angle symbols + (wc >= 0x2220 && wc <= 0x2222) || // ∠, ∡, ∢ + (wc >= 0x299b && wc <= 0x29af) || // ⦛, ⦜, ⦝, ⦞, ⦟, ⦠, ⦡, ⦢, ⦣, ⦤, ⦥, ⦦, ⦧, ⦨, ⦩, ⦪, ⦫, ⦬, ⦭, ⦮, ⦯ + + // Other_ID_Start + wc == 0x2118 || wc == 0x212E || // ℘, ℮ + (wc >= 0x309B && wc <= 0x309C) || // katakana-hiragana sound marks + + // bold-digits and double-struck digits + (wc >= 0x1D7CE && wc <= 0x1D7E1)); // 𝟎 through 𝟗 (inclusive), 𝟘 through 𝟡 (inclusive) +} + +static inline bool IsIdentifierFirstCharacter (int ch) { + if (IsASCII(ch)) { + return (bool) (isalpha(ch) || ch == '_'); + } + if (ch < 0xA1 || ch > 0x10ffff) { + return false; + } + + return is_wc_cat_id_start((uint32_t) ch); +} + +static inline bool IsIdentifierCharacter (int ch) { + if (IsASCII(ch)) { + return (bool) (isalnum(ch) || ch == '_' || ch == '!'); + } + if (ch < 0xA1 || ch > 0x10ffff) { + return false; + } + + if (is_wc_cat_id_start((uint32_t) ch)) { + return true; + } + + const CharacterCategory cat = CategoriseCharacter(ch); + + if (cat == ccMn || cat == ccMc || + cat == ccNd || cat == ccPc || + cat == ccSk || cat == ccMe || + cat == ccNo || + // primes (single, double, triple, their reverses, and quadruple) + (ch >= 0x2032 && ch <= 0x2037) || (ch == 0x2057)) { + return true; + } + return false; +} + +// keep the same function name to be easy to find again +static const uint32_t opsuffs[] = { + 0x00b2, // ² + 0x00b3, // ³ + 0x00b9, // ¹ + 0x02b0, // ʰ + 0x02b2, // ʲ + 0x02b3, // ʳ + 0x02b7, // ʷ + 0x02b8, // ʸ + 0x02e1, // ˡ + 0x02e2, // ˢ + 0x02e3, // ˣ + 0x1d2c, // ᴬ + 0x1d2e, // ᴮ + 0x1d30, // ᴰ + 0x1d31, // ᴱ + 0x1d33, // ᴳ + 0x1d34, // ᴴ + 0x1d35, // ᴵ + 0x1d36, // ᴶ + 0x1d37, // ᴷ + 0x1d38, // ᴸ + 0x1d39, // ᴹ + 0x1d3a, // ᴺ + 0x1d3c, // ᴼ + 0x1d3e, // ᴾ + 0x1d3f, // ᴿ + 0x1d40, // ᵀ + 0x1d41, // ᵁ + 0x1d42, // ᵂ + 0x1d43, // ᵃ + 0x1d47, // ᵇ + 0x1d48, // ᵈ + 0x1d49, // ᵉ + 0x1d4d, // ᵍ + 0x1d4f, // ᵏ + 0x1d50, // ᵐ + 0x1d52, // ᵒ + 0x1d56, // ᵖ + 0x1d57, // ᵗ + 0x1d58, // ᵘ + 0x1d5b, // ᵛ + 0x1d5d, // ᵝ + 0x1d5e, // ᵞ + 0x1d5f, // ᵟ + 0x1d60, // ᵠ + 0x1d61, // ᵡ + 0x1d62, // ᵢ + 0x1d63, // ᵣ + 0x1d64, // ᵤ + 0x1d65, // ᵥ + 0x1d66, // ᵦ + 0x1d67, // ᵧ + 0x1d68, // ᵨ + 0x1d69, // ᵩ + 0x1d6a, // ᵪ + 0x1d9c, // ᶜ + 0x1da0, // ᶠ + 0x1da5, // ᶥ + 0x1da6, // ᶦ + 0x1dab, // ᶫ + 0x1db0, // ᶰ + 0x1db8, // ᶸ + 0x1dbb, // ᶻ + 0x1dbf, // ᶿ + 0x2032, // ′ + 0x2033, // ″ + 0x2034, // ‴ + 0x2035, // ‵ + 0x2036, // ‶ + 0x2037, // ‷ + 0x2057, // ⁗ + 0x2070, // ⁰ + 0x2071, // ⁱ + 0x2074, // ⁴ + 0x2075, // ⁵ + 0x2076, // ⁶ + 0x2077, // ⁷ + 0x2078, // ⁸ + 0x2079, // ⁹ + 0x207a, // ⁺ + 0x207b, // ⁻ + 0x207c, // ⁼ + 0x207d, // ⁽ + 0x207e, // ⁾ + 0x207f, // ⁿ + 0x2080, // ₀ + 0x2081, // ₁ + 0x2082, // ₂ + 0x2083, // ₃ + 0x2084, // ₄ + 0x2085, // ₅ + 0x2086, // ₆ + 0x2087, // ₇ + 0x2088, // ₈ + 0x2089, // ₉ + 0x208a, // ₊ + 0x208b, // ₋ + 0x208c, // ₌ + 0x208d, // ₍ + 0x208e, // ₎ + 0x2090, // ₐ + 0x2091, // ₑ + 0x2092, // ₒ + 0x2093, // ₓ + 0x2095, // ₕ + 0x2096, // ₖ + 0x2097, // ₗ + 0x2098, // ₘ + 0x2099, // ₙ + 0x209a, // ₚ + 0x209b, // ₛ + 0x209c, // ₜ + 0x2c7c, // ⱼ + 0x2c7d, // ⱽ + 0xa71b, // ꜛ + 0xa71c, // ꜜ + 0xa71d // ꜝ +}; +static const size_t opsuffs_len = sizeof(opsuffs) / (sizeof(uint32_t)); + +// keep the same function name to be easy to find again +static bool jl_op_suffix_char(uint32_t wc) { + if (wc < 0xA1 || wc > 0x10ffff) { + return false; + } + const CharacterCategory cat = CategoriseCharacter((int) wc); + if (cat == ccMn || cat == ccMc || + cat == ccMe) { + return true; + } + + for (size_t i = 0; i < opsuffs_len; ++i) { + if (wc == opsuffs[i]) { + return true; + } + } + return false; +} + +// keep the same function name to be easy to find again +static bool never_id_char(uint32_t wc) { + const CharacterCategory cat = CategoriseCharacter((int) wc); + return ( + // spaces and control characters: + (cat >= ccZs && cat <= ccCs) || + + // ASCII and Latin1 non-connector punctuation + (wc < 0xff && + cat >= ccPd && cat <= ccPo) || + + wc == '`' || + + // mathematical brackets + (wc >= 0x27e6 && wc <= 0x27ef) || + // angle, corner, and lenticular brackets + (wc >= 0x3008 && wc <= 0x3011) || + // tortoise shell, square, and more lenticular brackets + (wc >= 0x3014 && wc <= 0x301b) || + // fullwidth parens + (wc == 0xff08 || wc == 0xff09) || + // fullwidth square brackets + (wc == 0xff3b || wc == 0xff3d)); +} + + +static bool IsOperatorFirstCharacter (int ch) { + if (IsASCII(ch)) { + if (IsJuliaOperator(ch) || + ch == '!' || ch == '?' || + ch == ':' || ch == ';' || + ch == ',' || ch == '.' ) { + return true; + }else { + return false; + } + } else if (is_wc_cat_id_start((uint32_t) ch)) { + return false; + } else if (IsJuliaUnaryOperator(ch) || + ! never_id_char((uint32_t) ch)) { + return true; + } + return false; +} + +static bool IsOperatorCharacter (int ch) { + if (IsOperatorFirstCharacter(ch) || + (!IsASCII(ch) && jl_op_suffix_char((uint32_t) ch)) ) { + return true; + } + return false; +} + +static bool CheckBoundsIndexing(char *str) { + if (strcmp("begin", str) == 0 || strcmp("end", str) == 0 ) { + return true; + } + return false; +} + +static int CheckKeywordFoldPoint(char *str) { + if (strcmp ("if", str) == 0 || + strcmp ("for", str) == 0 || + strcmp ("while", str) == 0 || + strcmp ("try", str) == 0 || + strcmp ("do", str) == 0 || + strcmp ("begin", str) == 0 || + strcmp ("let", str) == 0 || + strcmp ("baremodule", str) == 0 || + strcmp ("quote", str) == 0 || + strcmp ("module", str) == 0 || + strcmp ("struct", str) == 0 || + strcmp ("type", str) == 0 || + strcmp ("macro", str) == 0 || + strcmp ("function", str) == 0) { + return 1; + } + if (strcmp("end", str) == 0) { + return -1; + } + return 0; +} + +static bool IsNumberExpon(int ch, int base) { + if ((base == 10 && (ch == 'e' || ch == 'E' || ch == 'f')) || + (base == 16 && (ch == 'p' || ch == 'P'))) { + return true; + } + return false; +} + +/* Scans a sequence of digits, returning true if it found any. */ +static bool ScanDigits(StyleContext& sc, int base, bool allow_sep) { + bool found = false; + for (;;) { + if (IsADigit(sc.chNext, base) || (allow_sep && sc.chNext == '_')) { + found = true; + sc.Forward(); + } else { + break; + } + } + return found; +} + +static inline bool ScanNHexas(StyleContext &sc, int max) { + int n = 0; + bool error = false; + + sc.Forward(); + if (!IsADigit(sc.ch, 16)) { + error = true; + } else { + while (IsADigit(sc.ch, 16) && n < max) { + sc.Forward(); + n++; + } + } + return error; +} + +static void resumeCharacter(StyleContext &sc, bool lexerror) { + bool error = false; + + // ''' case + if (sc.chPrev == '\'' && sc.ch == '\'' && sc.chNext == '\'') { + sc.Forward(); + sc.ForwardSetState(SCE_JULIA_DEFAULT); + return; + } else if (lexerror && sc.chPrev == '\'' && sc.ch == '\'') { + sc.ChangeState(SCE_JULIA_LEXERROR); + sc.ForwardSetState(SCE_JULIA_DEFAULT); + + // Escape characters + } else if (sc.ch == '\\') { + sc.Forward(); + if (sc.ch == '\'' || sc.ch == '\\' ) { + sc.Forward(); + } else if (sc.ch == 'n' || sc.ch == 't' || sc.ch == 'a' || + sc.ch == 'b' || sc.ch == 'e' || sc.ch == 'f' || + sc.ch == 'r' || sc.ch == 'v' ) { + sc.Forward(); + } else if (sc.ch == 'x') { + error |= ScanNHexas(sc, 2); + } else if (sc.ch == 'u') { + error |= ScanNHexas(sc, 4); + } else if (sc.ch == 'U') { + error |= ScanNHexas(sc, 8); + } else if (IsADigit(sc.ch, 8)) { + int n = 1; + int max = 3; + sc.Forward(); + while (IsADigit(sc.ch, 8) && n < max) { + sc.Forward(); + n++; + } + } + + if (lexerror) { + if (sc.ch != '\'') { + error = true; + while (sc.ch != '\'' && + sc.ch != '\r' && + sc.ch != '\n') { + sc.Forward(); + } + } + + if (error) { + sc.ChangeState(SCE_JULIA_LEXERROR); + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } + } + } else if (lexerror) { + if (sc.ch < 0x20 || sc.ch > 0x10ffff) { + error = true; + } else { + // single character + sc.Forward(); + + if (sc.ch != '\'') { + error = true; + while (sc.ch != '\'' && + sc.ch != '\r' && + sc.ch != '\n') { + sc.Forward(); + } + } + } + + if (error) { + sc.ChangeState(SCE_JULIA_LEXERROR); + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } + } + + // closing quote + if (sc.ch == '\'') { + if (sc.chNext == '\'') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } + } +} + +static inline bool IsACharacter(StyleContext &sc) { + return (sc.chPrev == '\'' && sc.chNext == '\''); +} + +static void ScanParenInterpolation(StyleContext &sc) { + // TODO: no syntax highlighting inside a string interpolation + + // Level of nested parenthesis + int interp_level = 0; + + // If true, it is inside a string and parenthesis are not counted. + bool allow_paren_string = false; + + + // check for end of states + for (; sc.More(); sc.Forward()) { + // TODO: check corner cases for nested string interpolation + // TODO: check corner cases with Command inside interpolation + + if ( sc.ch == '\"' && sc.chPrev != '\\') { + // Toggle the string environment (parenthesis are not counted inside a string) + allow_paren_string = !allow_paren_string; + } else if ( !allow_paren_string ) { + if ( sc.ch == '(' && !IsACharacter(sc) ) { + interp_level ++; + } else if ( sc.ch == ')' && !IsACharacter(sc) && interp_level > 0 ) { + interp_level --; + if (interp_level == 0) { + // Exit interpolation + return; + } + } + } + } +} +/* + * Start parsing a number, parse the base. + */ +static void initNumber (StyleContext &sc, int &base, bool &with_dot) { + base = 10; + with_dot = false; + sc.SetState(SCE_JULIA_NUMBER); + if (sc.ch == '0') { + if (sc.chNext == 'x') { + sc.Forward(); + base = 16; + if (sc.chNext == '.') { + sc.Forward(); + with_dot = true; + } + } else if (sc.chNext == 'o') { + sc.Forward(); + base = 8; + } else if (sc.chNext == 'b') { + sc.Forward(); + base = 2; + } + } else if (sc.ch == '.') { + with_dot = true; + } +} + +/* + * Resume parsing a String or Command, bounded by the `quote` character (\" or \`) + * The `triple` argument specifies if it is a triple-quote String or Command. + * Interpolation is detected (with `$`), and parsed if `allow_interp` is true. + */ +static void resumeStringLike(StyleContext &sc, int quote, bool triple, bool allow_interp, bool full_highlight) { + int stylePrev = sc.state; + bool checkcurrent = false; + + // Escape characters + if (sc.ch == '\\') { + if (sc.chNext == quote || sc.chNext == '\\' || sc.chNext == '$') { + sc.Forward(); + } + } else if (allow_interp && sc.ch == '$') { + // If the interpolation is only of a variable, do not change state + if (sc.chNext == '(') { + if (full_highlight) { + sc.SetState(SCE_JULIA_STRINGINTERP); + } else { + sc.ForwardSetState(SCE_JULIA_STRINGINTERP); + } + ScanParenInterpolation(sc); + sc.ForwardSetState(stylePrev); + + checkcurrent = true; + + } else if (full_highlight && IsIdentifierFirstCharacter(sc.chNext)) { + sc.SetState(SCE_JULIA_STRINGINTERP); + sc.Forward(); + sc.Forward(); + for (; sc.More(); sc.Forward()) { + if (! IsIdentifierCharacter(sc.ch)) { + break; + } + } + sc.SetState(stylePrev); + + checkcurrent = true; + } + + if (checkcurrent) { + // Check that the current character is not a special char, + // otherwise it will be skipped + resumeStringLike(sc, quote, triple, allow_interp, full_highlight); + } + + } else if (sc.ch == quote) { + if (triple) { + if (sc.chNext == quote && sc.GetRelativeCharacter(2) == quote) { + // Move to the end of the triple quotes + Sci_PositionU nextIndex = sc.currentPos + 2; + while (nextIndex > sc.currentPos && sc.More()) { + sc.Forward(); + } + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } + } else { + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } + } +} + +static void resumeCommand(StyleContext &sc, bool triple, bool allow_interp) { + return resumeStringLike(sc, '`', triple, allow_interp, true); +} + +static void resumeString(StyleContext &sc, bool triple, bool allow_interp) { + return resumeStringLike(sc, '"', triple, allow_interp, true); +} + +static void resumeNumber (StyleContext &sc, int base, bool &with_dot, bool lexerror) { + if (IsNumberExpon(sc.ch, base)) { + if (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-') { + sc.Forward(); + // Capture all digits + ScanDigits(sc, 10, false); + sc.Forward(); + } + sc.SetState(SCE_JULIA_DEFAULT); + } else if (sc.ch == '.' && sc.chNext == '.') { + // Interval operator `..` + sc.SetState(SCE_JULIA_OPERATOR); + sc.Forward(); + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } else if (sc.ch == '.' && !with_dot) { + with_dot = true; + ScanDigits(sc, base, true); + } else if (IsADigit(sc.ch, base) || sc.ch == '_') { + ScanDigits(sc, base, true); + } else if (IsADigit(sc.ch) && !IsADigit(sc.ch, base)) { + if (lexerror) { + sc.ChangeState(SCE_JULIA_LEXERROR); + } + ScanDigits(sc, 10, false); + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } else { + sc.SetState(SCE_JULIA_DEFAULT); + } +} + +static void resumeOperator (StyleContext &sc) { + if (sc.chNext == ':' && (sc.ch == ':' || sc.ch == '<' || + (sc.ch == '>' && (sc.chPrev != '-' && sc.chPrev != '=')))) { + // Case `:a=>:b` + sc.Forward(); + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } else if (sc.ch == ':') { + // Case `foo(:baz,:baz)` or `:one+:two` + // Let the default case switch decide if it is a symbol + sc.SetState(SCE_JULIA_DEFAULT); + } else if (sc.ch == '\'') { + sc.SetState(SCE_JULIA_DEFAULT); + } else if ((sc.ch == '.' && sc.chPrev != '.') || IsIdentifierFirstCharacter(sc.ch) || + (! (sc.chPrev == '.' && IsOperatorFirstCharacter(sc.ch)) && + ! IsOperatorCharacter(sc.ch)) ) { + sc.SetState(SCE_JULIA_DEFAULT); + } +} + +void SCI_METHOD LexerJulia::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + PropSetSimple props; + Accessor styler(pAccess, &props); + + Sci_Position pos = startPos; + styler.StartAt(pos); + styler.StartSegment(pos); + + // use the line state of each line to store block/multiline states + Sci_Position curLine = styler.GetLine(startPos); + // Default is false for everything and 0 counters. + int lineState = (curLine > 0) ? styler.GetLineState(curLine-1) : 0; + + bool transpose = (lineState >> 0) & 0x01; // 1 bit to know if ' is allowed to mean transpose + bool istripledocstring = (lineState >> 1) & 0x01; // 1 bit to know if we are in a triple doublequotes string + bool triple_backtick = (lineState >> 2) & 0x01; // 1 bit to know if we are in a triple backtick command + bool israwstring = (lineState >> 3) & 0x01; // 1 bit to know if we are in a raw string + int indexing_level = (int)((lineState >> 4) & 0x0F); // 4 bits of bracket nesting counter + int list_comprehension = (int)((lineState >> 8) & 0x0F); // 4 bits of parenthesis nesting counter + int commentDepth = (int)((lineState >> 12) & 0x0F); // 4 bits of nested comment counter + + // base for parsing number + int base = 10; + // number has a float dot ? + bool with_dot = false; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + //// check for end of states + switch (sc.state) { + case SCE_JULIA_BRACKET: + sc.SetState(SCE_JULIA_DEFAULT); + break; + case SCE_JULIA_OPERATOR: + resumeOperator(sc); + break; + case SCE_JULIA_TYPEOPERATOR: + sc.SetState(SCE_JULIA_DEFAULT); + break; + case SCE_JULIA_TYPEANNOT: + if (! IsIdentifierCharacter(sc.ch)) { + sc.SetState(SCE_JULIA_DEFAULT); + } + break; + case SCE_JULIA_IDENTIFIER: + // String literal + if (sc.ch == '\"') { + // If the string literal has a prefix, interpolation is disabled + israwstring = true; + sc.ChangeState(SCE_JULIA_STRINGLITERAL); + sc.SetState(SCE_JULIA_DEFAULT); + + } else if (sc.ch == '`') { + // If the string literal has a prefix, interpolation is disabled + israwstring = true; + sc.ChangeState(SCE_JULIA_COMMANDLITERAL); + sc.SetState(SCE_JULIA_DEFAULT); + + // Continue if the character is an identifier character + } else if (! IsIdentifierCharacter(sc.ch)) { + char s[MAX_JULIA_IDENT_CHARS + 1]; + sc.GetCurrent(s, sizeof(s)); + + // Treat the keywords differently if we are indexing or not + if ( indexing_level > 0 && CheckBoundsIndexing(s)) { + // Inside [], (), `begin` and `end` are numbers not block keywords + sc.ChangeState(SCE_JULIA_NUMBER); + transpose = false; + + } else { + if (keywords.InList(s)) { + sc.ChangeState(SCE_JULIA_KEYWORD1); + transpose = false; + } else if (identifiers2.InList(s)) { + sc.ChangeState(SCE_JULIA_KEYWORD2); + transpose = false; + } else if (identifiers3.InList(s)) { + sc.ChangeState(SCE_JULIA_KEYWORD3); + transpose = false; + } else if (identifiers4.InList(s)) { + sc.ChangeState(SCE_JULIA_KEYWORD4); + // These identifiers can be used for variable names also, + // so transpose is not forbidden. + //transpose = false; + } + } + sc.SetState(SCE_JULIA_DEFAULT); + + // TODO: recognize begin-end blocks inside list comprehension + // b = [(begin n%2; n*2 end) for n in 1:10] + // TODO: recognize better comprehension for-if to avoid problem with code-folding + // c = [(if isempty(a); missing else first(b) end) for (a, b) in zip(l1, l2)] + } + break; + case SCE_JULIA_NUMBER: + resumeNumber(sc, base, with_dot, options.highlightLexerror); + break; + case SCE_JULIA_CHAR: + resumeCharacter(sc, options.highlightLexerror); + break; + case SCE_JULIA_DOCSTRING: + resumeString(sc, true, !israwstring); + if (sc.state == SCE_JULIA_DEFAULT && israwstring) { + israwstring = false; + } + break; + case SCE_JULIA_STRING: + resumeString(sc, false, !israwstring); + if (sc.state == SCE_JULIA_DEFAULT && israwstring) { + israwstring = false; + } + break; + case SCE_JULIA_COMMAND: + resumeCommand(sc, triple_backtick, !israwstring); + break; + case SCE_JULIA_MACRO: + if (IsASpace(sc.ch) || ! IsIdentifierCharacter(sc.ch)) { + sc.SetState(SCE_JULIA_DEFAULT); + } + break; + case SCE_JULIA_SYMBOL: + if (! IsIdentifierCharacter(sc.ch)) { + sc.SetState(SCE_JULIA_DEFAULT); + } + break; + case SCE_JULIA_COMMENT: + if( commentDepth > 0 ) { + // end or start of a nested a block comment + if ( sc.ch == '=' && sc.chNext == '#') { + commentDepth --; + sc.Forward(); + + if (commentDepth == 0) { + sc.ForwardSetState(SCE_JULIA_DEFAULT); + } + } else if( sc.ch == '#' && sc.chNext == '=') { + commentDepth ++; + sc.Forward(); + } + } else { + // single line comment + if (sc.atLineEnd || sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_JULIA_DEFAULT); + transpose = false; + } + } + break; + } + + // check start of a new state + if (sc.state == SCE_JULIA_DEFAULT) { + if (sc.ch == '#') { + sc.SetState(SCE_JULIA_COMMENT); + // increment depth if we are a block comment + if(sc.chNext == '=') { + commentDepth ++; + sc.Forward(); + } + } else if (sc.ch == '!') { + sc.SetState(SCE_JULIA_OPERATOR); + transpose = false; + } else if (sc.ch == '\'') { + if (transpose) { + sc.SetState(SCE_JULIA_OPERATOR); + } else { + sc.SetState(SCE_JULIA_CHAR); + } + } else if (sc.ch == '\"') { + istripledocstring = (sc.chNext == '\"' && sc.GetRelativeCharacter(2) == '\"'); + if (istripledocstring) { + sc.SetState(SCE_JULIA_DOCSTRING); + // Move to the end of the triple quotes + Sci_PositionU nextIndex = sc.currentPos + 2; + while (nextIndex > sc.currentPos && sc.More()) { + sc.Forward(); + } + } else { + sc.SetState(SCE_JULIA_STRING); + } + } else if (sc.ch == '`') { + triple_backtick = (sc.chNext == '`' && sc.GetRelativeCharacter(2) == '`'); + sc.SetState(SCE_JULIA_COMMAND); + if (triple_backtick) { + // Move to the end of the triple backticks + Sci_PositionU nextIndex = sc.currentPos + 2; + while (nextIndex > sc.currentPos && sc.More()) { + sc.Forward(); + } + } + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + initNumber(sc, base, with_dot); + } else if (IsIdentifierFirstCharacter(sc.ch)) { + sc.SetState(SCE_JULIA_IDENTIFIER); + transpose = true; + } else if (sc.ch == '@') { + sc.SetState(SCE_JULIA_MACRO); + transpose = false; + + // Several parsing of operators, should keep the order of `if` blocks + } else if ((sc.ch == ':' || sc.ch == '<' || sc.ch == '>') && sc.chNext == ':') { + sc.SetState(SCE_JULIA_TYPEOPERATOR); + sc.Forward(); + // Highlight the next identifier, if option is set + if (options.highlightTypeannotation && + IsIdentifierFirstCharacter(sc.chNext)) { + sc.ForwardSetState(SCE_JULIA_TYPEANNOT); + } + } else if (sc.ch == ':') { + // TODO: improve detection of range + // should be solved with begin-end parsing + // `push!(arr, s1 :s2)` and `a[begin :end] + if (IsIdentifierFirstCharacter(sc.chNext) && + ! IsIdentifierCharacter(sc.chPrev) && + sc.chPrev != ')' && sc.chPrev != ']' ) { + sc.SetState(SCE_JULIA_SYMBOL); + } else { + sc.SetState(SCE_JULIA_OPERATOR); + } + } else if (IsJuliaParen(sc.ch)) { + if (sc.ch == '[') { + list_comprehension ++; + indexing_level ++; + } else if (sc.ch == ']' && (indexing_level > 0)) { + list_comprehension --; + indexing_level --; + } else if (sc.ch == '(') { + list_comprehension ++; + } else if (sc.ch == ')' && (list_comprehension > 0)) { + list_comprehension --; + } + + if (sc.ch == ')' || sc.ch == ']' || sc.ch == '}') { + transpose = true; + } else { + transpose = false; + } + sc.SetState(SCE_JULIA_BRACKET); + } else if (IsOperatorFirstCharacter(sc.ch)) { + transpose = false; + sc.SetState(SCE_JULIA_OPERATOR); + } else { + transpose = false; + } + } + + // update the line information (used for line-by-line lexing and folding) + if (sc.atLineEnd) { + // set the line state to the current state + curLine = styler.GetLine(sc.currentPos); + + lineState = ((transpose ? 1 : 0) << 0) | + ((istripledocstring ? 1 : 0) << 1) | + ((triple_backtick ? 1 : 0) << 2) | + ((israwstring ? 1 : 0) << 3) | + ((indexing_level & 0x0F) << 4) | + ((list_comprehension & 0x0F) << 8) | + ((commentDepth & 0x0F) << 12); + styler.SetLineState(curLine, lineState); + } + } + sc.Complete(); +} + +void SCI_METHOD LexerJulia::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + int lineState = 0; + if (lineCurrent > 0) { + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + lineState = styler.GetLineState(lineCurrent-1); + } + + // level of nested brackets + int indexing_level = (int)((lineState >> 4) & 0x0F); // 4 bits of bracket nesting counter + // level of nested parenthesis or brackets + int list_comprehension = (int)((lineState >> 8) & 0x0F); // 4 bits of parenthesis nesting counter + //int commentDepth = (int)((lineState >> 12) & 0x0F); // 4 bits of nested comment counter + + Sci_PositionU lineStartNext = styler.LineStart(lineCurrent+1); + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int stylePrev = styler.StyleAt(startPos - 1); + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + char word[100]; + int wordlen = 0; + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = i == (lineStartNext-1); + + // a start/end of comment block + if (options.foldComment && style == SCE_JULIA_COMMENT) { + // start of block comment + if (ch == '#' && chNext == '=') { + levelNext ++; + } + // end of block comment + if (ch == '=' && chNext == '#' && levelNext > 0) { + levelNext --; + } + } + + // Syntax based folding, accounts for list comprehension + if (options.foldSyntaxBased) { + // list comprehension allow `for`, `if` and `begin` without `end` + if (style == SCE_JULIA_BRACKET) { + if (ch == '[') { + list_comprehension ++; + indexing_level ++; + levelNext ++; + } else if (ch == ']') { + list_comprehension --; + indexing_level --; + levelNext --; + } else if (ch == '(') { + list_comprehension ++; + levelNext ++; + } else if (ch == ')') { + list_comprehension --; + levelNext --; + } + // check non-negative + if (indexing_level < 0) { + indexing_level = 0; + } + if (list_comprehension < 0) { + list_comprehension = 0; + } + } + + // keyword + if (style == SCE_JULIA_KEYWORD1) { + word[wordlen++] = static_cast(ch); + if (wordlen == 100) { // prevent overflow + word[0] = '\0'; + wordlen = 1; + } + if (styleNext != SCE_JULIA_KEYWORD1) { + word[wordlen] = '\0'; + wordlen = 0; + if (list_comprehension <= 0 && indexing_level <= 0) { + levelNext += CheckKeywordFoldPoint(word); + } + } + } + } + + // Docstring + if (options.foldDocstring) { + if (stylePrev != SCE_JULIA_DOCSTRING && style == SCE_JULIA_DOCSTRING) { + levelNext ++; + } else if (style == SCE_JULIA_DOCSTRING && styleNext != SCE_JULIA_DOCSTRING) { + levelNext --; + } + } + + // check non-negative level + if (levelNext < 0) { + levelNext = 0; + } + + if (!IsASpace(ch)) { + visibleChars++; + } + stylePrev = style; + + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + lineStartNext = styler.LineStart(lineCurrent+1); + levelCurrent = levelNext; + if (atEOL && (i == static_cast(styler.Length() - 1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +extern const LexerModule lmJulia(SCLEX_JULIA, LexerJulia::LexerFactoryJulia, "julia", juliaWordLists); diff --git a/src/lexilla/lexers/LexKVIrc.cxx b/src/lexilla/lexers/LexKVIrc.cxx new file mode 100644 index 000000000..a9cd3582b --- /dev/null +++ b/src/lexilla/lexers/LexKVIrc.cxx @@ -0,0 +1,474 @@ +// Scintilla source code edit control +/** @file LexKVIrc.cxx + ** Lexer for KVIrc script. + **/ +// Copyright 2013 by OmegaPhil , based in +// part from LexPython Copyright 1998-2002 by Neil Hodgson +// and LexCmake Copyright 2007 by Cristian Adam + +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + + +/* KVIrc Script syntactic rules: http://www.kvirc.net/doc/doc_syntactic_rules.html */ + +/* Utility functions */ +static inline bool IsAWordChar(int ch) { + + /* Keyword list includes modules, i.e. words including '.', and + * alias namespaces include ':' */ + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' + || ch == ':'); +} +static inline bool IsAWordStart(int ch) { + + /* Functions (start with '$') are treated separately to keywords */ + return (ch < 0x80) && (isalnum(ch) || ch == '_' ); +} + +/* Interface function called by Scintilla to request some text to be + syntax highlighted */ +static void ColouriseKVIrcDoc(Sci_PositionU startPos, Sci_Position length, + int initStyle, WordList *keywordlists[], + Accessor &styler) +{ + /* Fetching style context */ + StyleContext sc(startPos, length, initStyle, styler); + + /* Accessing keywords and function-marking keywords */ + WordList &keywords = *keywordlists[0]; + WordList &functionKeywords = *keywordlists[1]; + + /* Looping for all characters - only automatically moving forward + * when asked for (transitions leaving strings and keywords do this + * already) */ + bool next = true; + for( ; sc.More(); next ? sc.Forward() : (void)0 ) + { + /* Resetting next */ + next = true; + + /* Dealing with different states */ + switch (sc.state) + { + case SCE_KVIRC_DEFAULT: + + /* Detecting single-line comments + * Unfortunately KVIrc script allows raw '#' to be used, and appending # to an array returns + * its length... + * Going for a compromise where single line comments not + * starting on a newline are allowed in all cases except + * when they are preceeded with an opening bracket or comma + * (this will probably be the most common style a valid + * string-less channel name will be used with), with the + * array length case included + */ + if ( + (sc.ch == '#' && sc.atLineStart) || + (sc.ch == '#' && ( + sc.chPrev != '(' && sc.chPrev != ',' && + sc.chPrev != ']') + ) + ) + { + sc.SetState(SCE_KVIRC_COMMENT); + break; + } + + /* Detecting multi-line comments */ + if (sc.Match('/', '*')) + { + sc.SetState(SCE_KVIRC_COMMENTBLOCK); + break; + } + + /* Detecting strings */ + if (sc.ch == '"') + { + sc.SetState(SCE_KVIRC_STRING); + break; + } + + /* Detecting functions */ + if (sc.ch == '$') + { + sc.SetState(SCE_KVIRC_FUNCTION); + break; + } + + /* Detecting variables */ + if (sc.ch == '%') + { + sc.SetState(SCE_KVIRC_VARIABLE); + break; + } + + /* Detecting numbers - isdigit is unsafe as it does not + * validate, use CharacterSet.h functions */ + if (IsADigit(sc.ch)) + { + sc.SetState(SCE_KVIRC_NUMBER); + break; + } + + /* Detecting words */ + if (IsAWordStart(sc.ch) && IsAWordChar(sc.chNext)) + { + sc.SetState(SCE_KVIRC_WORD); + sc.Forward(); + break; + } + + /* Detecting operators */ + if (isoperator(sc.ch)) + { + sc.SetState(SCE_KVIRC_OPERATOR); + break; + } + + break; + + case SCE_KVIRC_COMMENT: + + /* Breaking out of single line comment when a newline + * is introduced */ + if (sc.ch == '\r' || sc.ch == '\n') + { + sc.SetState(SCE_KVIRC_DEFAULT); + break; + } + + break; + + case SCE_KVIRC_COMMENTBLOCK: + + /* Detecting end of multi-line comment */ + if (sc.Match('*', '/')) + { + // Moving the current position forward two characters + // so that '*/' is included in the comment + sc.Forward(2); + sc.SetState(SCE_KVIRC_DEFAULT); + + /* Comment has been exited and the current position + * moved forward, yet the new current character + * has yet to be defined - loop without moving + * forward again */ + next = false; + break; + } + + break; + + case SCE_KVIRC_STRING: + + /* Detecting end of string - closing speechmarks */ + if (sc.ch == '"') + { + /* Allowing escaped speechmarks to pass */ + if (sc.chPrev == '\\') + break; + + /* Moving the current position forward to capture the + * terminating speechmarks, and ending string */ + sc.ForwardSetState(SCE_KVIRC_DEFAULT); + + /* String has been exited and the current position + * moved forward, yet the new current character + * has yet to be defined - loop without moving + * forward again */ + next = false; + break; + } + + /* Functions and variables are now highlighted in strings + * Detecting functions */ + if (sc.ch == '$') + { + /* Allowing escaped functions to pass */ + if (sc.chPrev == '\\') + break; + + sc.SetState(SCE_KVIRC_STRING_FUNCTION); + break; + } + + /* Detecting variables */ + if (sc.ch == '%') + { + /* Allowing escaped variables to pass */ + if (sc.chPrev == '\\') + break; + + sc.SetState(SCE_KVIRC_STRING_VARIABLE); + break; + } + + /* Breaking out of a string when a newline is introduced */ + if (sc.ch == '\r' || sc.ch == '\n') + { + /* Allowing escaped newlines */ + if (sc.chPrev == '\\') + break; + + sc.SetState(SCE_KVIRC_DEFAULT); + break; + } + + break; + + case SCE_KVIRC_FUNCTION: + case SCE_KVIRC_VARIABLE: + + /* Detecting the end of a function/variable (word) */ + if (!IsAWordChar(sc.ch)) + { + sc.SetState(SCE_KVIRC_DEFAULT); + + /* Word has been exited yet the current character + * has yet to be defined - loop without moving + * forward again */ + next = false; + break; + } + + break; + + case SCE_KVIRC_STRING_FUNCTION: + case SCE_KVIRC_STRING_VARIABLE: + + /* A function or variable in a string + * Detecting the end of a function/variable (word) */ + if (!IsAWordChar(sc.ch)) + { + sc.SetState(SCE_KVIRC_STRING); + + /* Word has been exited yet the current character + * has yet to be defined - loop without moving + * forward again */ + next = false; + break; + } + + break; + + case SCE_KVIRC_NUMBER: + + /* Detecting the end of a number */ + if (!IsADigit(sc.ch)) + { + sc.SetState(SCE_KVIRC_DEFAULT); + + /* Number has been exited yet the current character + * has yet to be defined - loop without moving + * forward */ + next = false; + break; + } + + break; + + case SCE_KVIRC_OPERATOR: + + /* Because '%' is an operator but is also the marker for + * a variable, I need to always treat operators as single + * character strings and therefore redo their detection + * after every character */ + sc.SetState(SCE_KVIRC_DEFAULT); + + /* Operator has been exited yet the current character + * has yet to be defined - loop without moving + * forward */ + next = false; + break; + + case SCE_KVIRC_WORD: + + /* Detecting the end of a word */ + if (!IsAWordChar(sc.ch)) + { + /* Checking if the word was actually a keyword - + * fetching the current word, NULL-terminated like + * the keyword list */ + char s[100]; + Sci_Position wordLen = sc.currentPos - styler.GetStartSegment(); + if (wordLen > 99) + wordLen = 99; /* Include '\0' in buffer */ + Sci_Position i; + for( i = 0; i < wordLen; ++i ) + { + s[i] = styler.SafeGetCharAt( styler.GetStartSegment() + i ); + } + s[wordLen] = '\0'; + + /* Actually detecting keywords and fixing the state */ + if (keywords.InList(s)) + { + /* The SetState call actually commits the + * previous keyword state */ + sc.ChangeState(SCE_KVIRC_KEYWORD); + } + else if (functionKeywords.InList(s)) + { + // Detecting function keywords and fixing the state + sc.ChangeState(SCE_KVIRC_FUNCTION_KEYWORD); + } + + /* Transitioning to default and committing the previous + * word state */ + sc.SetState(SCE_KVIRC_DEFAULT); + + /* Word has been exited yet the current character + * has yet to be defined - loop without moving + * forward again */ + next = false; + break; + } + + break; + } + } + + /* Indicating processing is complete */ + sc.Complete(); +} + +static void FoldKVIrcDoc(Sci_PositionU startPos, Sci_Position length, int /*initStyle - unused*/, + WordList *[], Accessor &styler) +{ + /* Based on CMake's folder */ + + /* Exiting if folding isnt enabled */ + if ( styler.GetPropertyInt("fold") == 0 ) + return; + + /* Obtaining current line number*/ + Sci_Position currentLine = styler.GetLine(startPos); + + /* Obtaining starting character - indentation is done on a line basis, + * not character */ + Sci_PositionU safeStartPos = styler.LineStart( currentLine ); + + /* Initialising current level - this is defined as indentation level + * in the low 12 bits, with flag bits in the upper four bits. + * It looks like two indentation states are maintained in the returned + * 32bit value - 'nextLevel' in the most-significant bits, 'currentLevel' + * in the least-significant bits. Since the next level is the most + * up to date, this must refer to the current state of indentation. + * So the code bitshifts the old current level out of existence to + * get at the actual current state of indentation + * Based on the LexerCPP.cxx line 958 comment */ + int currentLevel = SC_FOLDLEVELBASE; + if (currentLine > 0) + currentLevel = styler.LevelAt(currentLine - 1) >> 16; + int nextLevel = currentLevel; + + // Looping for characters in range + for (Sci_PositionU i = safeStartPos; i < startPos + length; ++i) + { + /* Folding occurs after syntax highlighting, meaning Scintilla + * already knows where the comments are + * Fetching the current state */ + int state = styler.StyleAt(i) & 31; + + switch( styler.SafeGetCharAt(i) ) + { + case '{': + + /* Indenting only when the braces are not contained in + * a comment */ + if (state != SCE_KVIRC_COMMENT && + state != SCE_KVIRC_COMMENTBLOCK) + ++nextLevel; + break; + + case '}': + + /* Outdenting only when the braces are not contained in + * a comment */ + if (state != SCE_KVIRC_COMMENT && + state != SCE_KVIRC_COMMENTBLOCK) + --nextLevel; + break; + + case '\n': + case '\r': + + /* Preparing indentation information to return - combining + * current and next level data */ + int lev = currentLevel | nextLevel << 16; + + /* If the next level increases the indent level, mark the + * current line as a fold point - current level data is + * in the least significant bits */ + if (nextLevel > currentLevel ) + lev |= SC_FOLDLEVELHEADERFLAG; + + /* Updating indentation level if needed */ + if (lev != styler.LevelAt(currentLine)) + styler.SetLevel(currentLine, lev); + + /* Updating variables */ + ++currentLine; + currentLevel = nextLevel; + + /* Dealing with problematic Windows newlines - + * incrementing to avoid the extra newline breaking the + * fold point */ + if (styler.SafeGetCharAt(i) == '\r' && + styler.SafeGetCharAt(i + 1) == '\n') + ++i; + break; + } + } + + /* At this point the data has ended, so presumably the end of the line? + * Preparing indentation information to return - combining current + * and next level data */ + int lev = currentLevel | nextLevel << 16; + + /* If the next level increases the indent level, mark the current + * line as a fold point - current level data is in the least + * significant bits */ + if (nextLevel > currentLevel ) + lev |= SC_FOLDLEVELHEADERFLAG; + + /* Updating indentation level if needed */ + if (lev != styler.LevelAt(currentLine)) + styler.SetLevel(currentLine, lev); +} + +/* Registering wordlists */ +static const char *const kvircWordListDesc[] = { + "primary", + "function_keywords", + 0 +}; + + +/* Registering functions and wordlists */ +extern const LexerModule lmKVIrc(SCLEX_KVIRC, ColouriseKVIrcDoc, "kvirc", FoldKVIrcDoc, + kvircWordListDesc); diff --git a/src/lexilla/lexers/LexKix.cxx b/src/lexilla/lexers/LexKix.cxx new file mode 100644 index 000000000..f87662627 --- /dev/null +++ b/src/lexilla/lexers/LexKix.cxx @@ -0,0 +1,137 @@ +// Scintilla source code edit control +/** @file LexKix.cxx + ** Lexer for KIX-Scripts. + **/ +// Copyright 2004 by Manfred Becker +// The License.txt file describes the conditions under which this software may be distributed. +// Edited by Lee Wilmott (24-Jun-2014) added support for block comments + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) { + return ch >= 0x80 || isalnum(ch) || ch == '_'; +} + +static inline bool IsOperator(const int ch) { + return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '|' || ch == '<' || ch == '>' || ch == '='); +} + +static void ColouriseKixDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; +// WordList &keywords4 = *keywordlists[3]; + + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_KIX_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_COMMENTSTREAM) { + if (sc.ch == '/' && sc.chPrev == '*') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_STRING1) { + // This is a doubles quotes string + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_STRING2) { + // This is a single quote string + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_NUMBER) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_VAR) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_MACRO) { + if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (!keywords3.InList(&s[1])) { + sc.ChangeState(SCE_KIX_DEFAULT); + } + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_OPERATOR) { + if (!IsOperator(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_KIX_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_KIX_FUNCTIONS); + } + sc.SetState(SCE_KIX_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_KIX_DEFAULT) { + if (sc.ch == ';') { + sc.SetState(SCE_KIX_COMMENT); + } else if (sc.ch == '/' && sc.chNext == '*') { + sc.SetState(SCE_KIX_COMMENTSTREAM); + } else if (sc.ch == '\"') { + sc.SetState(SCE_KIX_STRING1); + } else if (sc.ch == '\'') { + sc.SetState(SCE_KIX_STRING2); + } else if (sc.ch == '$') { + sc.SetState(SCE_KIX_VAR); + } else if (sc.ch == '@') { + sc.SetState(SCE_KIX_MACRO); + } else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) { + sc.SetState(SCE_KIX_NUMBER); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_KIX_OPERATOR); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(SCE_KIX_IDENTIFIER); + } + } + } + sc.Complete(); +} + + +extern const LexerModule lmKix(SCLEX_KIX, ColouriseKixDoc, "kix"); + diff --git a/src/lexilla/lexers/LexLaTeX.cxx b/src/lexilla/lexers/LexLaTeX.cxx new file mode 100644 index 000000000..e45df854a --- /dev/null +++ b/src/lexilla/lexers/LexLaTeX.cxx @@ -0,0 +1,563 @@ +// Scintilla source code edit control +/** @file LexLaTeX.cxx + ** Lexer for LaTeX2e. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// Modified by G. HU in 2013. Added folding, syntax highting inside math environments, and changed some minor behaviors. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "DefaultLexer.h" +#include "LexerBase.h" + +using namespace Scintilla; +using namespace Lexilla; + +using namespace std; + +struct latexFoldSave { + latexFoldSave() : structLev(0) { + for (int i = 0; i < 8; ++i) openBegins[i] = 0; + } + latexFoldSave(const latexFoldSave &save) : structLev(save.structLev) { + for (int i = 0; i < 8; ++i) openBegins[i] = save.openBegins[i]; + } + latexFoldSave &operator=(const latexFoldSave &save) { + if (this != &save) { + structLev = save.structLev; + for (int i = 0; i < 8; ++i) openBegins[i] = save.openBegins[i]; + } + return *this; + } + int openBegins[8]; + Sci_Position structLev; +}; + +class LexerLaTeX : public LexerBase { +private: + vector modes; + void setMode(Sci_Position line, int mode) { + if (line >= static_cast(modes.size())) modes.resize(line + 1, 0); + modes[line] = mode; + } + int getMode(Sci_Position line) { + if (line >= 0 && line < static_cast(modes.size())) return modes[line]; + return 0; + } + void truncModes(Sci_Position numLines) { + if (static_cast(modes.size()) > numLines * 2 + 256) + modes.resize(numLines + 128); + } + + vector saves; + void setSave(Sci_Position line, const latexFoldSave &save) { + if (line >= static_cast(saves.size())) saves.resize(line + 1); + saves[line] = save; + } + void getSave(Sci_Position line, latexFoldSave &save) { + if (line >= 0 && line < static_cast(saves.size())) save = saves[line]; + else { + save.structLev = 0; + for (int i = 0; i < 8; ++i) save.openBegins[i] = 0; + } + } + void truncSaves(Sci_Position numLines) { + if (static_cast(saves.size()) > numLines * 2 + 256) + saves.resize(numLines + 128); + } +public: + static ILexer5 *LexerFactoryLaTeX() { + return new LexerLaTeX(); + } + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + // ILexer5 methods + const char * SCI_METHOD GetName() override { + return "latex"; + } + int SCI_METHOD GetIdentifier() override { + return SCLEX_LATEX; + } +}; + +static bool latexIsSpecial(int ch) { + return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') || + (ch == '{') || (ch == '}') || (ch == ' '); +} + +static bool latexIsBlank(int ch) { + return (ch == ' ') || (ch == '\t'); +} + +static bool latexIsBlankAndNL(int ch) { + return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); +} + +static bool latexIsLetter(int ch) { + return IsASCII(ch) && isalpha(ch); +} + +static bool latexIsTagValid(Sci_Position &i, Sci_Position l, Accessor &styler) { + while (i < l) { + if (styler.SafeGetCharAt(i) == '{') { + while (i < l) { + i++; + if (styler.SafeGetCharAt(i) == '}') { + return true; + } else if (!latexIsLetter(styler.SafeGetCharAt(i)) && + styler.SafeGetCharAt(i)!='*') { + return false; + } + } + } else if (!latexIsBlank(styler.SafeGetCharAt(i))) { + return false; + } + i++; + } + return false; +} + +static bool latexNextNotBlankIs(Sci_Position i, Accessor &styler, char needle) { + char ch; + while (i < styler.Length()) { + ch = styler.SafeGetCharAt(i); + if (!latexIsBlankAndNL(ch) && ch != '*') { + if (ch == needle) + return true; + else + return false; + } + i++; + } + return false; +} + +static bool latexLastWordIs(Sci_Position start, Accessor &styler, const char *needle) { + Sci_PositionU i = 0; + Sci_PositionU l = static_cast(strlen(needle)); + Sci_Position ini = start-l+1; + char s[32]; + + while (i < l && i < 31) { + s[i] = styler.SafeGetCharAt(ini + i); + i++; + } + s[i] = '\0'; + + return (strcmp(s, needle) == 0); +} + +static bool latexLastWordIsMathEnv(Sci_Position pos, Accessor &styler) { + Sci_Position i, j; + char s[32]; + const char *mathEnvs[] = { "align", "alignat", "flalign", "gather", + "multiline", "displaymath", "eqnarray", "equation" }; + if (styler.SafeGetCharAt(pos) != '}') return false; + for (i = pos - 1; i >= 0; --i) { + if (styler.SafeGetCharAt(i) == '{') break; + if (pos - i >= 20) return false; + } + if (i < 0 || i == pos - 1) return false; + ++i; + for (j = 0; i + j < pos; ++j) + s[j] = styler.SafeGetCharAt(i + j); + s[j] = '\0'; + if (j == 0) return false; + if (s[j - 1] == '*') s[--j] = '\0'; + for (i = 0; i < static_cast(sizeof(mathEnvs) / sizeof(const char *)); ++i) + if (strcmp(s, mathEnvs[i]) == 0) return true; + return false; +} + +static inline void latexStateReset(int &mode, int &state) { + switch (mode) { + case 1: state = SCE_L_MATH; break; + case 2: state = SCE_L_MATH2; break; + default: state = SCE_L_DEFAULT; break; + } +} + +// There are cases not handled correctly, like $abcd\textrm{what is $x+y$}z+w$. +// But I think it's already good enough. +void SCI_METHOD LexerLaTeX::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + // startPos is assumed to be the first character of a line + Accessor styler(pAccess, &props); + styler.StartAt(startPos); + int mode = getMode(styler.GetLine(startPos) - 1); + int state = initStyle; + if (state == SCE_L_ERROR || state == SCE_L_SHORTCMD || state == SCE_L_SPECIAL) // should not happen + latexStateReset(mode, state); + + char chNext = styler.SafeGetCharAt(startPos); + char chVerbatimDelim = '\0'; + styler.StartSegment(startPos); + Sci_Position lengthDoc = startPos + length; + + for (Sci_Position i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + i++; + chNext = styler.SafeGetCharAt(i + 1); + continue; + } + + if (ch == '\r' || ch == '\n') + setMode(styler.GetLine(i), mode); + + switch (state) { + case SCE_L_DEFAULT : + switch (ch) { + case '\\' : + styler.ColourTo(i - 1, state); + if (latexIsLetter(chNext)) { + state = SCE_L_COMMAND; + } else if (latexIsSpecial(chNext)) { + styler.ColourTo(i + 1, SCE_L_SPECIAL); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chNext == '\r' || chNext == '\n') { + styler.ColourTo(i, SCE_L_ERROR); + } else if (IsASCII(chNext)) { + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + if (chNext == '(') { + mode = 1; + state = SCE_L_MATH; + } else if (chNext == '[') { + mode = 2; + state = SCE_L_MATH2; + } + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case '$' : + styler.ColourTo(i - 1, state); + if (chNext == '$') { + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + mode = 2; + state = SCE_L_MATH2; + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else { + styler.ColourTo(i, SCE_L_SHORTCMD); + mode = 1; + state = SCE_L_MATH; + } + break; + case '%' : + styler.ColourTo(i - 1, state); + state = SCE_L_COMMENT; + break; + } + break; + // These 3 will never be reached. + case SCE_L_ERROR: + case SCE_L_SPECIAL: + case SCE_L_SHORTCMD: + break; + case SCE_L_COMMAND : + if (!latexIsLetter(chNext)) { + styler.ColourTo(i, state); + if (latexNextNotBlankIs(i + 1, styler, '[' )) { + state = SCE_L_CMDOPT; + } else if (latexLastWordIs(i, styler, "\\begin")) { + state = SCE_L_TAG; + } else if (latexLastWordIs(i, styler, "\\end")) { + state = SCE_L_TAG2; + } else if (latexLastWordIs(i, styler, "\\verb") && chNext != '*' && chNext != ' ') { + chVerbatimDelim = chNext; + state = SCE_L_VERBATIM; + } else { + latexStateReset(mode, state); + } + } + break; + case SCE_L_CMDOPT : + if (ch == ']') { + styler.ColourTo(i, state); + latexStateReset(mode, state); + } + break; + case SCE_L_TAG : + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + latexStateReset(mode, state); + if (latexLastWordIs(i, styler, "{verbatim}")) { + state = SCE_L_VERBATIM; + } else if (latexLastWordIs(i, styler, "{lstlisting}")) { + state = SCE_L_VERBATIM; + } else if (latexLastWordIs(i, styler, "{comment}")) { + state = SCE_L_COMMENT2; + } else if (latexLastWordIs(i, styler, "{math}") && mode == 0) { + mode = 1; + state = SCE_L_MATH; + } else if (latexLastWordIsMathEnv(i, styler) && mode == 0) { + mode = 2; + state = SCE_L_MATH2; + } + } else { + styler.ColourTo(i, SCE_L_ERROR); + latexStateReset(mode, state); + ch = styler.SafeGetCharAt(i); + if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode); + } + chNext = styler.SafeGetCharAt(i+1); + break; + case SCE_L_TAG2 : + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + latexStateReset(mode, state); + } else { + styler.ColourTo(i, SCE_L_ERROR); + latexStateReset(mode, state); + ch = styler.SafeGetCharAt(i); + if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode); + } + chNext = styler.SafeGetCharAt(i+1); + break; + case SCE_L_MATH : + switch (ch) { + case '\\' : + styler.ColourTo(i - 1, state); + if (latexIsLetter(chNext)) { + Sci_Position match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{math}")) + mode = 0; + } + } + state = SCE_L_COMMAND; + } else if (latexIsSpecial(chNext)) { + styler.ColourTo(i + 1, SCE_L_SPECIAL); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chNext == '\r' || chNext == '\n') { + styler.ColourTo(i, SCE_L_ERROR); + } else if (IsASCII(chNext)) { + if (chNext == ')') { + mode = 0; + state = SCE_L_DEFAULT; + } + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case '$' : + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_L_SHORTCMD); + mode = 0; + state = SCE_L_DEFAULT; + break; + case '%' : + styler.ColourTo(i - 1, state); + state = SCE_L_COMMENT; + break; + } + break; + case SCE_L_MATH2 : + switch (ch) { + case '\\' : + styler.ColourTo(i - 1, state); + if (latexIsLetter(chNext)) { + Sci_Position match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIsMathEnv(match, styler)) + mode = 0; + } + } + state = SCE_L_COMMAND; + } else if (latexIsSpecial(chNext)) { + styler.ColourTo(i + 1, SCE_L_SPECIAL); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chNext == '\r' || chNext == '\n') { + styler.ColourTo(i, SCE_L_ERROR); + } else if (IsASCII(chNext)) { + if (chNext == ']') { + mode = 0; + state = SCE_L_DEFAULT; + } + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case '$' : + styler.ColourTo(i - 1, state); + if (chNext == '$') { + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i + 1); + mode = 0; + state = SCE_L_DEFAULT; + } else { // This may not be an error, e.g. \begin{equation}\text{$a$}\end{equation} + styler.ColourTo(i, SCE_L_SHORTCMD); + } + break; + case '%' : + styler.ColourTo(i - 1, state); + state = SCE_L_COMMENT; + break; + } + break; + case SCE_L_COMMENT : + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, state); + latexStateReset(mode, state); + } + break; + case SCE_L_COMMENT2 : + if (ch == '\\') { + Sci_Position match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{comment}")) { + styler.ColourTo(i - 1, state); + state = SCE_L_COMMAND; + } + } + } + } + break; + case SCE_L_VERBATIM : + if (ch == '\\') { + Sci_Position match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{verbatim}")) { + styler.ColourTo(i - 1, state); + state = SCE_L_COMMAND; + } else if (latexLastWordIs(match, styler, "{lstlisting}")) { + styler.ColourTo(i - 1, state); + state = SCE_L_COMMAND; + } + } + } + } else if (chNext == chVerbatimDelim) { + styler.ColourTo(i + 1, state); + latexStateReset(mode, state); + chVerbatimDelim = '\0'; + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) { + styler.ColourTo(i, SCE_L_ERROR); + latexStateReset(mode, state); + chVerbatimDelim = '\0'; + } + break; + } + } + if (lengthDoc == styler.Length()) truncModes(styler.GetLine(lengthDoc - 1)); + styler.ColourTo(lengthDoc - 1, state); + styler.Flush(); +} + +static int latexFoldSaveToInt(const latexFoldSave &save) { + int sum = 0; + for (int i = 0; i <= save.structLev; ++i) + sum += save.openBegins[i]; + return ((sum + save.structLev + SC_FOLDLEVELBASE) & SC_FOLDLEVELNUMBERMASK); +} + +// Change folding state while processing a line +// Return the level before the first relevant command +void SCI_METHOD LexerLaTeX::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess) { + const char *structWords[7] = {"part", "chapter", "section", "subsection", + "subsubsection", "paragraph", "subparagraph"}; + Accessor styler(pAccess, &props); + Sci_PositionU endPos = startPos + length; + Sci_Position curLine = styler.GetLine(startPos); + latexFoldSave save; + getSave(curLine - 1, save); + do { + char ch, buf[16]; + Sci_Position i, j; + int lev = -1; + bool needFold = false; + for (i = static_cast(startPos); i < static_cast(endPos); ++i) { + ch = styler.SafeGetCharAt(i); + if (ch == '\r' || ch == '\n') break; + if (ch != '\\' || styler.StyleAt(i) != SCE_L_COMMAND) continue; + for (j = 0; j < 15 && i + 1 < static_cast(endPos); ++j, ++i) { + buf[j] = styler.SafeGetCharAt(i + 1); + if (!latexIsLetter(buf[j])) break; + } + buf[j] = '\0'; + if (strcmp(buf, "begin") == 0) { + if (lev < 0) lev = latexFoldSaveToInt(save); + ++save.openBegins[save.structLev]; + needFold = true; + } + else if (strcmp(buf, "end") == 0) { + while (save.structLev > 0 && save.openBegins[save.structLev] == 0) + --save.structLev; + if (lev < 0) lev = latexFoldSaveToInt(save); + if (save.openBegins[save.structLev] > 0) --save.openBegins[save.structLev]; + } + else { + for (j = 0; j < 7; ++j) + if (strcmp(buf, structWords[j]) == 0) break; + if (j >= 7) continue; + save.structLev = j; // level before the command + for (j = save.structLev + 1; j < 8; ++j) { + save.openBegins[save.structLev] += save.openBegins[j]; + save.openBegins[j] = 0; + } + if (lev < 0) lev = latexFoldSaveToInt(save); + ++save.structLev; // level after the command + needFold = true; + } + } + if (lev < 0) lev = latexFoldSaveToInt(save); + if (needFold) lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(curLine, lev); + setSave(curLine, save); + ++curLine; + startPos = styler.LineStart(curLine); + if (static_cast(startPos) == styler.Length()) { + lev = latexFoldSaveToInt(save); + styler.SetLevel(curLine, lev); + setSave(curLine, save); + truncSaves(curLine); + } + } while (startPos < endPos); + styler.Flush(); +} + +static const char *const emptyWordListDesc[] = { + 0 +}; + +extern const LexerModule lmLatex(SCLEX_LATEX, LexerLaTeX::LexerFactoryLaTeX, "latex", emptyWordListDesc); diff --git a/src/lexilla/lexers/LexLisp.cxx b/src/lexilla/lexers/LexLisp.cxx new file mode 100644 index 000000000..519eaef4a --- /dev/null +++ b/src/lexilla/lexers/LexLisp.cxx @@ -0,0 +1,286 @@ +// Scintilla source code edit control +/** @file LexLisp.cxx + ** Lexer for Lisp. + ** Written by Alexey Yutkin. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +#define SCE_LISP_CHARACTER 29 +#define SCE_LISP_MACRO 30 +#define SCE_LISP_MACRO_DISPATCH 31 + +static inline bool isLispoperator(char ch) { + if (IsASCII(ch) && isalnum(ch)) + return false; + if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') + return true; + return false; +} + +static inline bool isLispwordstart(char ch) { + return IsASCII(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) && + ch != '\n' && ch != '\r' && ch != '\"'; +} + + +static void classifyWordLisp(Sci_PositionU start, Sci_PositionU end, WordList &keywords, WordList &keywords_kw, Accessor &styler) { + assert(end >= start); + char s[100]; + Sci_PositionU i; + bool digit_flag = true; + for (i = 0; (i < end - start + 1) && (i < 99); i++) { + s[i] = styler[start + i]; + s[i + 1] = '\0'; + if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false; + } + char chAttr = SCE_LISP_IDENTIFIER; + + if(digit_flag) chAttr = SCE_LISP_NUMBER; + else { + if (keywords.InList(s)) { + chAttr = SCE_LISP_KEYWORD; + } else if (keywords_kw.InList(s)) { + chAttr = SCE_LISP_KEYWORD_KW; + } else if ((s[0] == '*' && s[i-1] == '*') || + (s[0] == '+' && s[i-1] == '+')) { + chAttr = SCE_LISP_SPECIAL; + } + } + styler.ColourTo(end, chAttr); + return; +} + + +static void ColouriseLispDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords_kw = *keywordlists[1]; + + styler.StartAt(startPos); + + int state = initStyle, radix = -1; + char chNext = styler[startPos]; + Sci_PositionU lengthDoc = startPos + length; + styler.StartSegment(startPos); + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i += 1; + continue; + } + + if (state == SCE_LISP_DEFAULT) { + if (ch == '#') { + styler.ColourTo(i - 1, state); + radix = -1; + state = SCE_LISP_MACRO_DISPATCH; + } else if (ch == ':' && isLispwordstart(chNext)) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_SYMBOL; + } else if (isLispwordstart(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_IDENTIFIER; + } + else if (ch == ';') { + styler.ColourTo(i - 1, state); + state = SCE_LISP_COMMENT; + } + else if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + else if (ch == '\"') { + styler.ColourTo(i - 1, state); + state = SCE_LISP_STRING; + } + } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) { + if (!isLispwordstart(ch)) { + if (state == SCE_LISP_IDENTIFIER) { + classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler); + } else { + styler.ColourTo(i - 1, state); + } + state = SCE_LISP_DEFAULT; + } /*else*/ + if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + } else if (state == SCE_LISP_MACRO_DISPATCH) { + if (!(IsASCII(ch) && isdigit(ch))) { + if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) { + state = SCE_LISP_DEFAULT; + } else { + switch (ch) { + case '|': state = SCE_LISP_MULTI_COMMENT; break; + case 'o': + case 'O': radix = 8; state = SCE_LISP_MACRO; break; + case 'x': + case 'X': radix = 16; state = SCE_LISP_MACRO; break; + case 'b': + case 'B': radix = 2; state = SCE_LISP_MACRO; break; + case '\\': state = SCE_LISP_CHARACTER; break; + case ':': + case '-': + case '+': state = SCE_LISP_MACRO; break; + case '\'': if (isLispwordstart(chNext)) { + state = SCE_LISP_SPECIAL; + } else { + styler.ColourTo(i - 1, SCE_LISP_DEFAULT); + styler.ColourTo(i, SCE_LISP_OPERATOR); + state = SCE_LISP_DEFAULT; + } + break; + default: if (isLispoperator(ch)) { + styler.ColourTo(i - 1, SCE_LISP_DEFAULT); + styler.ColourTo(i, SCE_LISP_OPERATOR); + } + state = SCE_LISP_DEFAULT; + break; + } + } + } + } else if (state == SCE_LISP_MACRO) { + if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) { + state = SCE_LISP_SPECIAL; + } else { + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_CHARACTER) { + if (isLispoperator(ch)) { + styler.ColourTo(i, SCE_LISP_SPECIAL); + state = SCE_LISP_DEFAULT; + } else if (isLispwordstart(ch)) { + styler.ColourTo(i, SCE_LISP_SPECIAL); + state = SCE_LISP_SPECIAL; + } else { + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_SPECIAL) { + if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_DEFAULT; + } + if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + } else { + if (state == SCE_LISP_COMMENT) { + if (atEOL) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_MULTI_COMMENT) { + if (ch == '|' && chNext == '#') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + styler.ColourTo(i, state); + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_STRING) { + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, state); + state = SCE_LISP_DEFAULT; + } + } + } + + } + styler.ColourTo(lengthDoc - 1, state); +} + +static void FoldLispDoc(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[], + Accessor &styler) { + Sci_PositionU lengthDoc = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + for (Sci_PositionU i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_LISP_OPERATOR) { + if (ch == '(' || ch == '[' || ch == '{') { + levelCurrent++; + } else if (ch == ')' || ch == ']' || ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const lispWordListDesc[] = { + "Functions and special operators", + "Keywords", + 0 +}; + +extern const LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc); diff --git a/src/lexilla/lexers/LexLout.cxx b/src/lexilla/lexers/LexLout.cxx new file mode 100644 index 000000000..999c63316 --- /dev/null +++ b/src/lexilla/lexers/LexLout.cxx @@ -0,0 +1,216 @@ +// Scintilla source code edit control +/** @file LexLout.cxx + ** Lexer for the Basser Lout (>= version 3) typesetting language + **/ +// Copyright 2003 by Kein-Hong Man +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +using namespace Lexilla; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_'); +} + +static inline bool IsAnOther(const int ch) { + return (ch < 0x80) && (ch == '{' || ch == '}' || + ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' || + ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' || + ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' || + ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' || + ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~'); +} + +static void ColouriseLoutDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + + int visibleChars = 0; + int firstWordInLine = 0; + int leadingAtSign = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) { + // Prevent SCE_LOUT_STRINGEOL from leaking back to previous line + sc.SetState(SCE_LOUT_STRING); + } + + // Determine if the current state should terminate. + if (sc.state == SCE_LOUT_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_LOUT_DEFAULT); + visibleChars = 0; + } + } else if (sc.state == SCE_LOUT_NUMBER) { + if (!IsADigit(sc.ch) && sc.ch != '.') { + sc.SetState(SCE_LOUT_DEFAULT); + } + } else if (sc.state == SCE_LOUT_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_LOUT_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_LOUT_STRINGEOL); + sc.ForwardSetState(SCE_LOUT_DEFAULT); + visibleChars = 0; + } + } else if (sc.state == SCE_LOUT_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (leadingAtSign) { + if (keywords.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD); + } else { + sc.ChangeState(SCE_LOUT_WORD4); + } + } else if (firstWordInLine && keywords3.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD3); + } + sc.SetState(SCE_LOUT_DEFAULT); + } + } else if (sc.state == SCE_LOUT_OPERATOR) { + if (!IsAnOther(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (keywords2.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD2); + } + sc.SetState(SCE_LOUT_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_LOUT_DEFAULT) { + if (sc.ch == '#') { + sc.SetState(SCE_LOUT_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_LOUT_STRING); + } else if (IsADigit(sc.ch) || + (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_LOUT_NUMBER); + } else if (IsAWordChar(sc.ch)) { + firstWordInLine = (visibleChars == 0); + leadingAtSign = (sc.ch == '@'); + sc.SetState(SCE_LOUT_IDENTIFIER); + } else if (IsAnOther(sc.ch)) { + sc.SetState(SCE_LOUT_OPERATOR); + } + } + + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldLoutDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], + Accessor &styler) { + + Sci_PositionU endPos = startPos + length; + int visibleChars = 0; + Sci_Position lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int styleNext = styler.StyleAt(startPos); + char s[10] = ""; + + for (Sci_PositionU i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_LOUT_WORD) { + if (ch == '@') { + for (Sci_PositionU j = 0; j < 8; j++) { + if (!IsAWordChar(styler[i + j])) { + break; + } + s[j] = styler[i + j]; + s[j + 1] = '\0'; + } + if (strcmp(s, "@Begin") == 0) { + levelCurrent++; + } else if (strcmp(s, "@End") == 0) { + levelCurrent--; + } + } + } else if (style == SCE_LOUT_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const loutWordLists[] = { + "Predefined identifiers", + "Predefined delimiters", + "Predefined keywords", + 0, + }; + +extern const LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists); diff --git a/src/lexilla/lexers/LexLua.cxx b/src/lexilla/lexers/LexLua.cxx new file mode 100644 index 000000000..f8ea1e35e --- /dev/null +++ b/src/lexilla/lexers/LexLua.cxx @@ -0,0 +1,646 @@ +// Scintilla source code edit control +/** @file LexLua.cxx + ** Lexer for Lua language. + ** + ** Written by Paul Winwood. + ** Folder by Alexey Yutkin. + ** Modified by Marcos E. Wurzius & Philippe Lhoste + **/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SubStyles.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { + +// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ], +// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on. +// The maximum number of '=' characters allowed is 254. +int LongDelimCheck(StyleContext &sc) { + constexpr int maximumEqualCharacters = 254; + int sep = 1; + while (sc.GetRelative(sep) == '=' && sep <= maximumEqualCharacters) + sep++; + if (sc.GetRelative(sep) == sc.ch) + return sep; + return 0; +} + +const char *const luaWordListDesc[] = { + "Keywords", + "Basic functions", + "String, (table) & math functions", + "(coroutines), I/O & system facilities", + "user1", + "user2", + "user3", + "user4", + nullptr +}; + +const char styleSubable[] = { SCE_LUA_IDENTIFIER, 0 }; + +const LexicalClass lexicalClasses[] = { + // Lexer Lua SCLEX_LUA SCE_LUA_: + 0, "SCE_LUA_DEFAULT", "default", "White space: Visible only in View Whitespace mode (or if it has a back colour)", + 1, "SCE_LUA_COMMENT", "comment", "Block comment (Lua 5.0)", + 2, "SCE_LUA_COMMENTLINE", "comment line", "Line comment", + 3, "SCE_LUA_COMMENTDOC", "comment documentation", "Doc comment", + 4, "SCE_LUA_NUMBER", "literal numeric", "Number", + 5, "SCE_LUA_WORD", "keyword", "Keyword", + 6, "SCE_LUA_STRING", "literal string", "(Double quoted) String", + 7, "SCE_LUA_CHARACTER", "literal string character", "Character (Single quoted string)", + 8, "SCE_LUA_LITERALSTRING", "literal string", "Literal string", + 9, "SCE_LUA_PREPROCESSOR", "preprocessor", "Preprocessor (obsolete in Lua 4.0 and up)", + 10, "SCE_LUA_OPERATOR", "operator", "Operators", + 11, "SCE_LUA_IDENTIFIER", "identifier", "Identifier (everything else...)", + 12, "SCE_LUA_STRINGEOL", "error literal string", "End of line where string is not closed", + 13, "SCE_LUA_WORD2", "identifier", "Other keywords", + 14, "SCE_LUA_WORD3", "identifier", "Other keywords", + 15, "SCE_LUA_WORD4", "identifier", "Other keywords", + 16, "SCE_LUA_WORD5", "identifier", "Other keywords", + 17, "SCE_LUA_WORD6", "identifier", "Other keywords", + 18, "SCE_LUA_WORD7", "identifier", "Other keywords", + 19, "SCE_LUA_WORD8", "identifier", "Other keywords", + 20, "SCE_LUA_LABEL", "label", "Labels", +}; + +// Options used for LexerLua +struct OptionsLua { + bool foldCompact = true; +}; + +struct OptionSetLua : public OptionSet { + OptionSetLua() { + DefineProperty("fold.compact", &OptionsLua::foldCompact); + + DefineWordListSets(luaWordListDesc); + } +}; + +class LexerLua : public DefaultLexer { + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList keywords5; + WordList keywords6; + WordList keywords7; + WordList keywords8; + OptionsLua options; + OptionSetLua osLua; + SubStyles subStyles{styleSubable}; +public: + explicit LexerLua() : + DefaultLexer("lua", SCLEX_LUA, lexicalClasses, std::size(lexicalClasses)) { + } + LexerLua(const LexerLua &) = delete; + LexerLua(LexerLua &&) = delete; + LexerLua &operator=(const LexerLua &) = delete; + LexerLua &operator=(LexerLua &&) = delete; + ~LexerLua() override = default; + void SCI_METHOD Release() noexcept override { + delete this; + } + [[nodiscard]] int SCI_METHOD Version() const noexcept override { + return lvRelease5; + } + const char *SCI_METHOD PropertyNames() noexcept override { + return osLua.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osLua.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) override { + return osLua.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char *SCI_METHOD PropertyGet(const char *key) override { + return osLua.PropertyGet(key); + } + const char *SCI_METHOD DescribeWordListSets() noexcept override { + return osLua.DescribeWordListSets(); + } + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) override { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) override { + return subStyles.Length(styleBase); + } + int SCI_METHOD StyleFromSubStyle(int subStyle) override { + const int styleBase = subStyles.BaseStyle(subStyle); + return styleBase; + } + int SCI_METHOD PrimaryStyleFromStyle(int style) override { + return style; + } + void SCI_METHOD FreeSubStyles() override { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override { + subStyles.SetIdentifiers(style, identifiers); + } + int SCI_METHOD DistanceToSecondaryStyles() override { + return 0; + } + const char *SCI_METHOD GetSubStyleBases() override { + return styleSubable; + } + + static ILexer5 *LexerFactoryLua() { + return new LexerLua(); + } +}; + +Sci_Position SCI_METHOD LexerLua::PropertySet(const char *key, const char *val) { + if (osLua.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerLua::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &keywords5; + break; + case 5: + wordListN = &keywords6; + break; + case 6: + wordListN = &keywords7; + break; + case 7: + wordListN = &keywords8; + break; + default: + break; + } + Sci_Position firstModification = -1; + if (wordListN) { + if (wordListN->Set(wl)) { + firstModification = 0; + } + } + return firstModification; +} + +constexpr int maskSeparator = 0xFF; +constexpr int maskStringWs = 0x100; +constexpr int maskDocComment = 0x200; + +void LexerLua::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + // Accepts accented characters + const CharacterSet setWordStart(CharacterSet::setAlpha, "_", true); + const CharacterSet setWord(CharacterSet::setAlphaNum, "_", true); + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. [pP] is for hex floats. + const CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP"); + const CharacterSet setExponent("eEpP"); + const CharacterSet setLuaOperator("*/-+()={}~[];<>,.^%:#&|"); + const CharacterSet setEscapeSkip("\"'\\"); + + const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_LUA_IDENTIFIER); + + Sci_Position currentLine = styler.GetLine(startPos); + // Initialize long string [[ ... ]] or block comment --[[ ... ]], + // if we are inside such a string. Block comment was introduced in Lua 5.0, + // blocks with separators [=[ ... ]=] in Lua 5.1. + // Continuation of a string (\z whitespace escaping) is controlled by stringWs. + int sepCount = 0; + int stringWs = 0; + int lastLineDocComment = 0; + if ((currentLine > 0) && + AnyOf(initStyle, SCE_LUA_DEFAULT, SCE_LUA_LITERALSTRING, SCE_LUA_COMMENT, SCE_LUA_COMMENTDOC, SCE_LUA_STRING, SCE_LUA_CHARACTER)) { + const int lineState = styler.GetLineState(currentLine - 1); + sepCount = lineState & maskSeparator; + stringWs = lineState & maskStringWs; + lastLineDocComment = lineState & maskDocComment; + } + + // results of identifier/keyword matching + Sci_Position idenPos = 0; + Sci_Position idenStartCharWidth = 0; + Sci_Position idenWordPos = 0; + int idenStyle = SCE_LUA_IDENTIFIER; + bool foundGoto = false; + + // Do not leak onto next line + if (AnyOf(initStyle, SCE_LUA_STRINGEOL, SCE_LUA_COMMENTLINE, SCE_LUA_COMMENTDOC, SCE_LUA_PREPROCESSOR)) { + initStyle = SCE_LUA_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + if (startPos == 0 && sc.ch == '#' && sc.chNext == '!') { + // shbang line: "#!" is a comment only if located at the start of the script + sc.SetState(SCE_LUA_COMMENTLINE); + } + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + currentLine = styler.GetLine(sc.currentPos); + switch (sc.state) { + case SCE_LUA_DEFAULT: + case SCE_LUA_LITERALSTRING: + case SCE_LUA_COMMENT: + case SCE_LUA_COMMENTDOC: + case SCE_LUA_STRING: + case SCE_LUA_CHARACTER: + // Inside a literal string, block comment or string, we set the line state + styler.SetLineState(currentLine, lastLineDocComment | stringWs | sepCount); + break; + default: + // Reset the line state + styler.SetLineState(currentLine, 0); + break; + } + } + if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) { + // Prevent SCE_LUA_STRINGEOL from leaking back to previous line + sc.SetState(SCE_LUA_STRING); + } + + // Handle string line continuation + if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) && + sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_LUA_OPERATOR) { + if (sc.ch == ':' && sc.chPrev == ':') { // ::